how this pointer works in arrays? - c++

Here is the code.
#include <iostream>
using namespace std;
int w=0;
class A{
int k,n;
public:
int z;
A(){w+=3; k=3+w; n=4+w; z=w;}
A *fun1(){z=k*n; return this;}
A *fun2(){z=n*k; return this-1;}
friend int fun (A *a,int &b);
};
int fun(A *a,int &b)
{ b=a->z+=4;
return a->k+a->n;
}
int main()
{ int m;
A a[2];
cout<<fun(a[1].fun1(),m)<<"\n";
cout<<m<<"\n";
cout<<fun(a[1].fun2(),m)<<"\n";
cout<<m<<"\n";
cout<<a[0].z+a[1].z<<"\n";
return 0;
}
When return this-1 happens, what does it mean? Does it mean that the object returned is a[0]? I can't understand..
Thanks!

Like any pointer, subtracting 1 from this assumes *this is an element of an array, gives the address of the preceding object in the array. There is an implicit assumption in A::fun2() that *this is an element of an array, and that there is at least one preceding element in that array.
So, in your sample code, a[1].fun2() returns the the address of a[0]. i.e. &a[0].
a[0].fun2() would return a (pointer) value equal to &a[-1]. Notionally, that is a pointer to a non-existent object. Computing this-1 in A::fun2() would give undefined behaviour just as much as computing a-1 would in main(). One common (but not guaranteed) practical symptom of such undefined behaviour would be a program crashing when later dereferencing the pointer.

A fun2(){z=nk; return this-1;}
'this' is a self-referential pointer. You cannot subtract 1 from this.
It will then point to a memory location which is one before 'this' pointer

Related

Returning arrays from a function in c++

I am trying to return an array from a function:
#include <iostream>
using namespace std;
int* uni(int *a,int *b)
{
int c[10];
int i=0;
while(a[i]!=-1)
{
c[i]=a[i];
i++;
}
for(;i<10;i++)
c[i]=b[i-5];
return c;
}
int main()
{
int a[10]={1,3,3,8,4,-1,-1,-1,-1,-1};
int b[5]={1,3,4,3,0};
int *c=uni(a,b);
for(int i=0;i<10;i++)
cout<<c[i]<<" ";
cout<<"\n";
return 0;
}
I pass two arrays from my main() into my uni() function. There I create a new array c[10] which I return to my main().
In my uni() function I try to merge the non-negative numbers in the two arrays a and b.
But I get something like this as my output.
1 -1078199700 134514080 -1078199656 -1216637148 134519488 134519297 134519488 8 -1078199700
Whereas when I try to print the values of c[10] in the uni() function it prints the correct values. Why does this happen??
Is this something related to the stack?? Because I have tried searching about this error of mine, and I found a few places on stackoverflow, where it says that do not allocate on stack but I couldn't understand it.
Further it would become very easy if I allocate my array globally, but if this is the case then everything shall be declared globally?? Why are we even worried about passing pointers from functions?? (I have a chapter in my book for passing pointers)
Admittedly, the std::vector or std::array approach would be the way to go.
However, just to round things out (and if this is a school project, where the teacher gives you the obligatory "you can't use STL"), the other alternative that will avoid pointer usage is to wrap the array inside a struct and return the instance of the struct.
#include <iostream>
using namespace std;
struct myArray
{
int array[10];
};
myArray uni(int *a,int *b)
{
myArray c;
int i=0;
while(a[i]!=-1)
{
c.array[i]=a[i];
i++;
}
for(;i<10;i++)
c.array[i]=b[i-5];
return c;
}
int main()
{
int a[10]={1,3,3,8,4,-1,-1,-1,-1,-1};
int b[5]={1,3,4,3,0};
myArray c = uni(a,b);
for(int i=0;i<10;i++)
cout << c.array[i] << " ";
cout << "\n";
return 0;
}
Note that the struct is returned by value, and this return value is assigned in main.
You have the value semantics of returning an instance, plus the struct will get copied, including the array that is internal within it.
Live Example
You're returning a pointer to a local object. In the uni function, the variable c is allocated on the stack. At the end of that function, all of that memory is released and in your for loop you are getting undefined results.
As suggested in the comments, std::array or std::vector will give you copy constructors that will allow you to return the object by value as you're trying to do. Otherwise you'll have to resort to something like passing your output array in as an argument.
You are returning a pointer to an array that is being deallocated at the return statement. It's a dangling pointer. It's UB.
Use an std::vector or std::array and return by value. There are compiler optimizations that will avoid inefficiencies.

Why doesn't this pointer get the value at the array index?

#include <iostream>
using namespace std;
int func(int arg0, int *arg1, int *arg2);
int main() {
int *b;
int z;
int a[10];
z = func(*a[0], &a[z], b+a[4]);
}
The following code above gives me an error "invalid type argument of unary '*' (have 'int')". I know that * when used in a declaration creates a pointer and when used with a variable name it gets the value stored at that pointer. In the function func(), it takes 3 parameters, 1 int and 2 int pointers. I think that the first argument passed into the function is giving me an error but I am not understanding why. Shouldn't *a[0] get the value of the first element in the a array which was declared as an int?
No, the * when used on a pointer dereferences the pointer. But a[0] is already equivalent to:
*(a + 0) // And since the offset is 0, this is equivalent to *a.
In other words, dereferencing a pointer to the beginning of the array that has been offset to give you the value of the item at a given 'index'. What YOU wrote is equivalent to:
**(a + 0) // And since the offset is 0, this is equivalent to **a.
Therefore, you are trying to 'dereference' an int, which won't work. Since * is not a valid unary operator for an int, that fails and causes the error you've seen to appear.
*a[0] is the same as **a.
Given the declaration int a[10];, it should be fairly clear that you are not able to dereference a twice.
If you want the first element of the array a, then that is simply a[0].
You could also simplify your example to this, and still get the same error:
int main() {
int a[10];
int b = *a[0];
}

If an array name is treated as a pointer, why do I get a compile time error of Lvalue required when incrementing an array?

int main()
{
int a[]={2,3,4,5,6};
int j;
for(j=0;j<5;j++)
{
printf("%d\n",*a);
a++;
}
return;
}
gives "Lvalue required" error but
int main()
{
int a[]={2,3,4,5,6};
int *p,j;
p=a;
for(j=0;j<5;j++)
{
printf("%d\n",*p);
p++;
}
return;
}
doesn't. why????
Though closely related, arrays are not pointers. The name of the array is just a label to identify some allocated memory (hence, the Lvalue error when you try to modify it).
An array is not a pointer. In most expressions, an array is converted to a pointer automatically. The result of this conversion is no longer the array; it is just a pointer value.
The ++ operator cannot operate on a mere value. It must have an object to act on.
For example, consider int x = 3; (x+5)++;. The result of x+5 is 8. It is not x. The result is just a value, not an object, so there is no object containing 8 that ++ can operate on. This is an error.
Similarly, if a is an array of int, then a++ is equivalent to ((int *) a)++. The ++ is not trying to act on the a; it is trying to act on the result of converting a to a pointer.
An array expression is always converted to a pointer to the first element except when the array expression is the operand of sizeof, &, or _Alignof or is a string literal used to initialize an array.
This will display all the array data.
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
int main()
{
int a[]={2,3,4,5,6};
int *p,j;
p=a;
for(j=0;j<5;j++)
{
printf("%d\n",p[j]);
}
return 0;
}

Pointers and recurency - I'm trying to save memory

I'm trying to write program that create squere for string. Squere has to be larger then string.length(). If there is word 'C++' I need 2x2 array to fill it inside.
So I have written code
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
int pole(int &a,const int* l);
int main(){
string code;
cin >> code;
int wall=1;
pole(wall,code.length());
cout << wall;
system("PAUSE");
return 0;
}
int pole(int &a,const int* l){
if (a*a > l) return a;
else {
a+=1;
pole(a,l);
}
}
I bet that using pointer with recunrency save a lot of memory but I can't compile it. I'm trying to understand compilers error but is 2 hard for me ;/
Here is compiler list of errors
> in main()
11 25 Error] invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int (*)(int&, const int*)'
6 5> [Error] in passing argument 1 of 'int pole(int&, const int*)'
in pole() 17 12
>[Error] ISO C++ forbids comparison between pointer and
> integer [-fpermissive]
Here:
pole(pole, code.length());
You are passing as the second variable the result of length(), which is of type std::string::size_type, which the function pole accepts a pointer to int. Those two types are incompatible.
The second problem is that one branch of your if statement inside pole does not contain a return statement, thus giving your program Undefined Behavior.
You may want to change your function pole this way:
int pole(int &a, std::string::size_type l) {
// ^^^^^^^^^^^^^^^^^^^^^^
// Also, passing by reference is unnecessary here
if (a*a > static_cast<int>(l)) return a;
// ^^^^^^^^^^^^^^^^
// Just to communicate that you are aware of the
// signed-to-unsigned comparison here
else {
a+=1;
return pole(a,l);
// ^^^^^^
// Do not forget this, or your program will have Undefined Behavior!
}
}
Here you can see your modified program compile and run.
You are trying to use an unsigned integer (coming from std::string::length) as a pointer in:
pole(wall,code.length());
Change your pole declarations to:
int pole(int a, int l);
Saving memory on int is just nonsense there. Pointers are sometimes even more memory expensive than simple integers.
You should learn to save memory with huge objects instead.
int pole(int &a,const int* l){
if (a*a > l) return a;
else {
a+=1;
pole(a,l);
}
}
first, you cannot initialize int* l with size_t argument.
Also you do later comparison between address, not value pointed too.
Is this what you wanted?

Returning an array ... rather a reference or pointer to an array

I am a bit confused. There are two ways to return an array from a method. The first suggests the following:
typedef int arrT[10];
arrT *func(int i);
However, how do I capture the return which is an int (*)[]?
Another way is through a reference or pointer:
int (*func(int i)[10];
or
int (&func(int i)[10];
The return types are either int (*)[] or int (&)[].
The trouble I am having is how I can assign a variable to accept the point and I continue to get errors such as:
can't convert int* to int (*)[]
Any idea what I am doing wrong or what is lacking in my knowledge?
If you want to return an array by value, put it in a structure.
The Standard committee already did that, and thus you can use std::array<int,10>.
std::array<int,10> func(int i);
std::array<int,10> x = func(77);
This makes it very straightforward to return by reference also:
std::array<int,10>& func2(int i);
std::array<int,10>& y = func2(5);
First, the information you give is incorrect.
You write,
“There are two ways to return an array from a method”
and then you give as examples of the ways
typedef int arrT[10];
arrT *func(int i);
and
int (*func(int i))[10];
(I’ve added the missing right parenthesis), where you say that this latter way, in contrast to the first, is an example of
“through a reference or pointer”
Well, these two declarations mean exactly the same, to wit:
typedef int A[10];
A* fp1( int i ) { return 0; }
int (*fp2( int i ))[10] { return 0; }
int main()
{
int (*p1)[10] = fp1( 100 );
int (*p2)[10] = fp2( 200 );
}
In both cases a pointer to the array is returned, and this pointer is typed as "pointer to array". Dereferencing that pointer yields the array itself, which decays to a pointer to itself again, but now typed as "pointer to item". It’s a pointer to the first item of the array. At the machine code level these two pointers are, in practice, exactly the same. Coming from a Pascal background that confused me for a long time, but the upshot is, since it’s generally impractical to carry the array size along in the type (which precludes dealing with arrays of different runtime sizes), most array handling code deals with the pointer-to-first-item instead of the pointer-to-the-whole-array.
I.e., normally such a low level C language like function would be declared as just
int* func()
return a pointer to the first item of an array of size established at run time.
Now, if you want to return an array by value then you have two choices:
Returning a fixed size array by value: put it in a struct.
The standard already provides a templated class that does this, std::array.
Returning a variable size array by value: use a class that deals with copying.
The standard already provides a templated class that does this, std::vector.
For example,
#include <vector>
using namespace std;
vector<int> foo() { return vector<int>( 10 ); }
int main()
{
vector<int> const v = foo();
// ...
}
This is the most general. Using std::array is more of an optimization for special cases. As a beginner, keep in mind Donald Knuth’s advice: “Premature optimization is the root of all evil.” I.e., just use std::vector unless there is a really really good reason to use std::array.
using arrT10 = int[10]; // Or you can use typedef if you want
arrT10 * func(int i)
{
arrT10 a10;
return &a10;
// int a[10];
// return a; // ERROR: can't convert int* to int (*)[]
}
This will give you a warning because func returns an address of a local variable so we should NEVER code like this but I'm sure this code can help you.