Under most circumstances1, an expression of type "N-element array of T
" will be converted ("decay") to expression of type "pointer to T
", and the value of the expression will be the address of the first element in the array.
The expression c
has type int [1][1]
; by the rule above, the expression will decay to type int (*)[1]
, or "pointer to 1-element array of int
", and its value will be the same as &c[0]
. If we dereference this pointer (as in the expression *c
), we get an expression of type "1-element array of int
", which, by the rule above again, decays to an expression of type int *
, and its value will be the same as &c[0][0]
.
The address of the first element of the array is the same as the address of the array itself, so &c
== &c[0]
== &c[0][0]
== c
== *c
== c[0]
. All of those expressions will resolve to the same address, even though they don't have the same types (int (*)[1][1]
, int (*)[1]
, int *
, int (*)[1]
, int *
, and int *
, respectively).
1 - the exceptions to this rule are when the array expression is an operand of the sizeof
, _Alignof
, or unary &
operators, or is a string literal being used to initialize another array in a declaration