Another way to look at it is through the resulting type after each address of or dereference operation. A basic rule for array access is Array-pointer conversion. C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) which applies on access to any array (subject to the 4 exceptions listed [3 in the C18 standard -- _Alignof
is no longer listed]).
The key is to understand that an array, on access, is converted to a pointer to the first element (subject to limited exception - not relevant here). If you take the address of an array, the address is the same as that of the first element, but the type of pointer is completely different.
a - pointer to int
&a - pointer-to-array int[4], proper type: int (*)[4]
When you dereference a
, you get the first element:
*a - int
Why? *a
is short for the full derefernce operation with an offset of 0
, e.g. *(a + 0)
which is equivalent to a[0]
in index notation.
When you dereference your pointer-to-array int[4]
, you get your array back:
*(&a) - int[4] -> converted to pointer to first element.
which then, by operation of, 6.3.2.1(p3) is converted to a pointer to the first element. Dereference again and you get the first element:
**(&a) - int
It's worth learning now as it will save you a lot of bewilderment later.