Arrays and pointers are two different types in C++ that have enough similarities between them to create confusion if they are not understood properly. The fact that pointers are one of the most difficult concepts for beginners to grasp doesn't help either.
So I fell a quick crash course is needed.
Crash course
Arrays, easy
int a[3] = {2, 3, 4};
This creates an array named a
that contains 3 elements.
Arrays have defined the array subscript operator:
a[i]
evaluates to the i
'th element of the array.
Pointers, easy
int val = 24;
int* p = &val;
p
is a pointer pointing to the address of the object val
.
Pointers have the indirection (dereference) operator defined:
*p
evaluates to the value of the object pointed by p
.
Pointers, acting like arrays
Pointers give you the address of an object in memory. It can be a "standalone object" like in the example above, or it can be an object that is part of an array. Neither the pointer type nor the pointer value can tell you which one it is. Just the programmer. That's why
Pointers also have the array subscript operator defined:
p[i]
evaluates to the i
th element to the "right" of the object pointed by p
. This assumes that the object pointer by p
is part of an array (except in p[0]
where it doesn't need to be part of an array).
Note that p[0]
is equivalent to (the exact same as) *p
.
Arrays, acting like pointers
In most contexts array names decay to a pointer to the first element in the array. That is why many beginners think that arrays and pointers are the same thing. In fact they are not. They are different types.
Your examples
Going back to your examples.
Why can a pointer to the first element &a[0]
point to array elements, or values in general,
Now I hope you can see that if p
points to the first element of the array arr
then p[i]
is equivalent to arr[i]
. Since &a[0]
is a pointer to the first element of the array then (&a[0])[i]
is equivalent to a[i]
.
... but the pointer &a
cannot?
As I stated above, arrays are not pointer.
So a pointer to the array is not the same thing as a pointer to the first element of the array. Taking the address of the array is one of the few instances where the array name doesn't decay to a pointer to its first element.
So &a
is a pointer to the array, not a pointer to the first element of the array. Both the array and the first element of the array start at the same address so the values of the two (&a
and &a[0]
) are the same, but their types are different and that matters when you apply the dereference or array subscript operator to them:
Expression |
Expression type |
Dereference / array subscript expresison |
Dereference / array subscript type |
a |
int[3] |
*a / a[i] |
int |
&a |
int (*) [3] (pointer to array) |
*&a / &a[i] |
int[3] |
&a[0] |
int * |
*&a[0] / (&a[0])[i] |
int |