a
is a synonym (by definition) for &a[0]
as K&R gently explain in "Arrays and Pointers" chapter. &a
is not mentioned, but can be regarded as intermediate step.
You have to concentrate on the identifier, here a
. All the compiler needs is the address where a
begins and what type its elements are. The 2nd element is bound to be at the base address plus one element size.
&a
and &a[0]
are rather expressions to evaluate than values to store. Also &a[23]
is calculated, not stored: a + 23 * elemsize.
printf("%p\n", a );
printf("%p\n", a+1 ); // address of next element, not byte
printf("%p\n", &(a[1]) ); // parens not needed
The 2nd and 3rd line print an address 8 bytes (long size) above the array start.
at 0x7ff9c94a10 exists there the address itself
Maybe that address really exists at the same spot. like we all somehow do. But it holds a long "6".
To fill an array with its addresses you can:
void *a[3];
for (int i = 0; i < 3; i++)
a[i] = &a[i];
for (int i = 0; i < 3; i++) {
printf("%p\n", a[i]);
printf("%p\n", &a[i]);
}
prints:
0x7ffe0918cbe0
0x7ffe0918cbe0
0x7ffe0918cbe8
0x7ffe0918cbe8
0x7ffe0918cbf0
0x7ffe0918cbf0
It takes 8 bytes to store an address/pointer. long
and void *
have same size here.
printf("%p\n", a+i);
also works. No need to take reference of a derefernced element: &a[i]
.
One basic array-and-pointer rule is the E1[E2] is *(E1 + E2)
. E1 has to designate an array, and E2 and integer, so
a[i]
*(a + i)
are the same. As are
&(a[i])
&a[i]
a + 1
The idea of an array starting at a defined address is simple. But to talk about it...natural language can live with double senses:
"Have you seen number 12 today?" (the guest)
"Did you clean number 12?" (not the guest, the room)
bafflement
Somehow. But while after void **b = a;
you can use the pointer b
just like a
(only that it has its own new &b
) a = ...
is not possible (assignment to the naked array).
New Example
Your long
type was good for really storing pointers to something, but it made the above example complex. Here a simple int array, so nobody gets tempted to store addresses. It shows what an array and a pointer share and what not:
int main(){
int a[3] = {10,20,30};
int *b;
b = a;
for (int i = 0; i < 3; i++) {
printf("%p\n", &a[i]);
printf("%p\n", &b[i]);
printf("%p %d\n", a+i, a[i]);
printf("%p %d\n", b+i, b[i]);
}
printf("%p\n", a);
printf("%p b = a\n", b);
printf("%p\n", &a);
printf("%p <-- different, &b != &a\n", &b);
return 0;
}
This gives:
0x7fff72f0ed8c
0x7fff72f0ed8c
0x7fff72f0ed8c 10
0x7fff72f0ed8c 10
0x7fff72f0ed90
0x7fff72f0ed90
0x7fff72f0ed90 20
0x7fff72f0ed90 20
0x7fff72f0ed94
0x7fff72f0ed94
0x7fff72f0ed94 30
0x7fff72f0ed94 30
0x7fff72f0ed8c
0x7fff72f0ed8c b = a (same as top index zero)
0x7fff72f0ed8c
0x7fff72f0ed80 <-- different, &b != &a
The difference (12 bytes, "0" for a "c") is not dramatic, but that does not matter. b
has a life besides the array elements, a
not.
Along with that goes the fact that the pointer b
can be assigned to (as done with b = a
), but the array a
not.
How come ?
the addresses of array, &array, &array[0]
This is actually very unclear. The address of array
is &array
(somehow), but the address of &array
is neither &&array
(errror about a label 'array') nor &(&array
) (error: lvalue required).