In the code below, I declare an int array "a" and then a pointer to the entire array "ap":
int main(){
int a[3] = {10, 100, 1000};
int (*ap)[] = &a;
printf("%p\n", ap);
printf("%p\n", *ap);
printf("%d\n", **ap);
return 0;
}
The first print of ap shows that it is actually a pointer to the first value of the array. OK.
But in the second print, ap is dereferenced and, yet, the value is the same: pointer to the first value of the array.
It's only after a "double dereferencing" that I get the value of the first array element (10 in my example):
0x7fff193310cc
0x7fff193310cc
10
Why is that so?
Thanks a lot!
CodePudding user response:
When you do *ap
it's basically the same as doing *(&a)
, which is in essence plain a
.
And as arrays decays to pointers to their first elements, plain a
is the same as &a[0]
.
Now here's the interesting thing: The location of the array a
and the location of the first element of a
is the exact same location.
It's easy to see if we draw it out:
------ ------ ------ | a[0] | a[1] | a[2] | ------ ------ ------ ^ | &a[0] | &a
See how both &a[0]
and &a
are pointing to the same location?
But also remember that while both &a[0]
and &a
are pointing to the same location, they have very different types:
&a[0]
will have the typeint *
&a
will have the typeint (*)[3]
CodePudding user response:
ap
is a pointer to an array. In the program execution you observed, the array starts at address 7FFF193310CC16.
Since ap
is a pointer to an array, *ap
is an array. When an array is used in an expression other than as the operand of unary &
, the operand of sizeof
, or as a string literal used to initialize an array, it is automatically converted to a pointer to its first element. Therefore, *ap
is converted to a pointer to (*ap)[0]
. Naturally, the first element of an array starts in the same place the array does, since it is the first thing in the array, so its address is 7FFF193310CC16.
Since *ap
is automatically converted to a pointer to (*ap)[0]
, **ap
is the thing it points to, which is (*ap)[0]
, so it is the first element of the array, not a pointer.
Note that, to have behavior defined by the C standard when printing a pointer, you should convert it to void *
:
printf("%p\n", (void *) ap);
printf("%p\n", (void *) *ap);
CodePudding user response:
------ --------- ----------
| 10 | 100 | 1000 |
------ --------- ----------
^ ^ ^
| | |
| | ------
| --- --
&ap | |
*ap **ap
&ap
points to the base address of the array, its type isint (*)[3]
(pointer to array with 3int
elements).*ap
points to the first element of the array, its type isint *
(pointer toint
).**ap
yields the value stored at the address of the first element, its type isint
.
But in the second print, ap is dereferenced and, yet, the value is the same: pointer to the first value of the array.
The name of an array in C usually yields the address of the first element of the array.
However when you use the &
operator in an expression such as &arrayname
, it yields a pointer of type T(*)[size]
instead of "pointer to the first element".
This means &a
and a
both have the same value, but they have completely different types, hence why ap
and *ap
also have the same value but different types.
CodePudding user response:
You declared a pointer to an object of the type int[3].
int (*ap)[] = &a;
So the call of printf prints the address of the object of the type int[3]
printf("%p\n", ap);
Dereferencing the pointer you get an array of an unknown size due to this declaration of the pointer int (*ap)[]
. Array designators used in expressions with rare exceptions are converted to pointers to their first elements. So the address of the first element of the array is outputted in this call of printf
printf("%p\n", *ap);
The addresses of the array itself and of its first element are equal each other.