There seems to be some misunderstanding in how pointers and arrays work together.
The expression &a
is a pointer to the array itself, and has the type int (*)[5]
.
What you seem to expect is to get a pointer to the first element, which would be &a[0]
, or plain a
(as that decays to a pointer to the arrays first element):
int *p = a;
That it works is not a coincidence, because a pointer to the array just happens to point to the same address as the location of the first element. The addresses are equal, but the types of &a
and &a[0]
are different. This semantic difference really is crucial.
Regarding the issue about the ++
operator, it's simply how it works.
The result of the suffix increase or decrease operators is the old value. So when you do p++
you get the old pointer, before the increase.
If we take
i = *p++;
it's (somewhat simplified) equivalent to
int *temporary_old_p = p;
p = p + 1;
i = *temporary_old_p;
Furthermore, the "%u"
format for a pointer is invalid. To print a void *
pointer (a cast is really needed to be correct) you should use the "%p"
format specifier.
Mismatching format-specifier and argument type leads to undefined behavior.
Regarding the problem with *(&a + 1)
, lets draw the array a
how it looks in memory, with a few arrows to show pointers:
+------+------+------+------+------+------
| a[0] | a[1] | a[2] | a[3] | a[4] | ....
+------+------+------+------+------+------
^ ^
| |
&a[0] |
| |
&a &a + 1
Since the type of &a
is int (*)[5]
, then it follows that the type of &a + 1
should also be int (*)[5]
.
If we dereference the pointer &a
(as in *(&a)
) then we get the actual array a
. Arrays, like a
, decay to a pointer to its first element, &a[0]
. This pointer is pointing to the same location as &a
(as shown in the "drawing" above).
If we change &a
to &a + 1
, then we get *(&a + 1)
in the dereference. It's the "second" array (is it existed). Just like *(&a)
is an array of five int
, so is *(&a + 1)
. This array decays to a pointer to its first element &(*(&a + 1))[0]
.
Or perhaps think that &a
is equal to &a + 0
. Then it would be easy to see that *(&a)
would be equal to *(&a + 0)
. And we know that *(&a)
is equal to a
which is equal to &a[0]
, which also means that *(&a + 0)
have to be equal to &(*(&a + 0))[0]
. That should make it easy to see what &(*(&a + 1))[0]
might be.