Blub
Blub

Reputation: 13614

Pointer to pointer array understanding problem

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?

Upvotes: 7

Views: 26990

Answers (4)

Chubsdad
Chubsdad

Reputation: 25497

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.

Upvotes: 1

AndersK
AndersK

Reputation: 36082

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.

Upvotes: 19

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506897

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.

Upvotes: 9

Marcelo Cantos
Marcelo Cantos

Reputation: 185842

The expression *(test + 1) is equivalent to test[1], so your code could be rewritten thus:

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

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

cout << *test[1];

Since test[1] obviously points to x, *test[1] is 7.

Just to be clear, the expression **(test + 1) is simply equivalent to *(*(test + 1)), which is in turn equivalent to *test[1].

Upvotes: 0

Related Questions