Reputation: 13614
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
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
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
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
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