Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer to pointer array understanding problem

Tags:

c++

pointers

This is probably a stupid question, but I don't understand why this works:

 int** test = new int*[7];

 int x = 7;
 *(test+1) = &x;

 cout << (**(test+1));

test is a pointer to a pointer right? The second pointer points to the array, right? In my understand I would need to dereference the "test" pointer first to get to the pointer that has the array.

(*test) // Now I have int*
*((*test) + 1) // to access the first element.

Where is my faulty thinking?

like image 272
Blub Avatar asked Sep 05 '10 12:09

Blub


3 Answers

int** test = new int*[7];

+------++------++------++------++------++------++------+
| int* || int* || int* || int* || int* || int* || int* |
+------++------++------++------++------++------++------+

is the equivalent of an array with int pointers:

int* test[0] 
int* test[1] 
...
int* test[6] 

this

int x = 7;
 *(test+1) = &x;

+------++------++------++------++------++------++------+
| int* || &x   || int* || int* || int* || int* || int* |
+------++------++------++------++------++------++------+

is the same as

int x = 7;
test[1] = &x

so now one of the pointers in your original array is pointing the memory location of x

 cout << (**(test+1));

is the same as

cout << *test[1] 

which is the value of x (==7) and which both test[1] and &x point to.

like image 69
AndersK Avatar answered Oct 19 '22 12:10

AndersK


Is your misunderstanding that you think you have created a pointer to an array of 7 int? You haven't. You actually have created an array of 7 pointers to int. So there is no "second pointer" here that would point to an array. There is just one pointer that points to the first of the 7 pointers (test).

And with *test you get that first pointer which you haven't initialized yet, though. If you would add 1 to that, you would add 1 to some random address. But if you add 1 to test you get a pointer that points to the second pointer of the array. And dererencing that you get that second pointer, which you did initialize.


What you describe would be achieved by a different syntax

typedef int array[7];
array* test = new int[1][7];

// Note: "test" is a pointer to an array of int. 
// There are already 7 integers! You cannot make it
// point to an int somehow. 
*(*test + 1) = 7;

int *p1 = *test
int i1 = *(p1 + 1); // i1 is 7, second element of the int[7]

delete[] test;

Without using the typedef, this looks like the following

int(*test)[7] = new int[1][7];

That is, you have created a one-element array, where the element-type of that is a 7-element array of int. new gives you a pointer back to that array. Note that the parenthesis is important: The * has less precedence than the [7], so otherwise this would be taken as an array of 7 pointer to integers.

like image 20
Johannes Schaub - litb Avatar answered Oct 19 '22 12:10

Johannes Schaub - litb


Suppose that

test[0] = 0x12345678;   // some pointer value
test[1] = 0x23456789;   // some pointer value

*test = 0x12345678;

*test + 1 is now 0x12345678 + 1 = 0x12345679;

* or dereference operator has higher precedence than binary +). So the expression is evaluated in that order.

However what you wanted for is to get to test[0] = 0x23456789;

So the correct expression to get to test[1] = (*(test + 1))

In general arr[i] is *(arr + i)

EDIT 2:

given

int buf[10] = {0, 1, 2};
int *p = buf;

buf[0] == p[0] == *(p + 0) equal to 0.

Note that it is perfectly fine to use array access syntax with the lvalue expression p even if it is not an array type. In fact the expression buf[0] is internally translated by the compiler to *(buf + 0) as well.

like image 1
Chubsdad Avatar answered Oct 19 '22 14:10

Chubsdad