I have maybe a very naive question (I am no expert in C programming), but I couldn't get a fully satisfactory explanation. Here is just the declaration of static array and a few prints:
#include <stdlib.h>
#include <stdio.h>
void main() {
int N=3, a[N];
for (int i=0; i<N; i++) a[i] = 1000+i;
printf("&a = %p\n",&a);
printf("a = %p\n",a);
printf("*a = %d\n",*a);
printf("*(&a) = %d (as an int)\n",*(&a));
printf("*(&a) = %p\ (as a pointer)\n",*(&a));
}
The output is:
&a = 0x7ffee9043ae0
a = 0x7ffee9043ae0
*a = 1000
*(&a) = -319989024 (as an int)
*(&a) = 0x7ffee9043ae0 (as a pointer)
Since &a and a are identical, showing the same address in memory, I was first expecting *(&a) and *a being identical as well, both equal to 1000.
Then I thought about the types: a is apparently considered as an int*, so &a is a int**. It turns that *a is an int, while *(&a) is an int*: they are not of the same type, the latter is a pointer.
It makes sense... But my question is then: why are &a and a identical in the first place?
The variable a according to its declaration has the array type a[N] that is a[3]. It is a variable length array.
Arrays used in expressions with rare exceptions are converted to pointers to their first elements.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
So this call of printf
printf("a = %p\n",a);
in fact is the same as
printf("a = %p\n",&a[0]);
The expression &a has the pointer type int ( * )[N] (not int **).
These two calls of printf
printf("&a = %p\n",&a);
printf("a = %p\n",a);
yield the same value because the address of an array as whole and the address of the first element of the array are equal each other and represent the address of the extent of memory allocated for the array. Though as it was mentioned the expressions have different types
The expression *( &a ) is equivalent to the expression a. So this call of printf
printf("*(&a) = %d (as an int)\n",*(&a));
is equivalent to
printf("*(&a) = %d (as an int)\n",a);
and invokes undefined behavior because there is used the invalid format specification %d with a pointer.
And the output of this call of printf
printf("*(&a) = %p\ (as a pointer)\n",*(&a))
yields the same value
a = 0x7ffee9043ae0
*(&a) = 0x7ffeeced5ae0 (as a pointer)
as this call of printf
printf("a = %p\n",a);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With