Except when it is the operand of the sizeof
or unary &
operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T
" is converted ("decays") to an expression of type "pointer to T
", and the value of the expression is the address of the first element of the array.
So given a declaration like
int a[100];
any time a
appears in an expression where it isn't the operand of the sizeof
or unary &
operators, the compiler will treat it as a pointer expression equivalent to &a[0]
(type int *
).
Now, what happens if a
is the operand of unary &
?
The address of an array is the same as the address of the first element of the array, which should be clear from the diagram below:
+------+
a: | a[0] |
+------+
| a[1] |
+------+
...
+------+
| a[99]|
+------+
The type of the expression &a
is int (*)[100]
(pointer to 100-element array of int
), but the value of the expression is the same as a
and &a[0]
(address of the first element).
Summarizing that in a table:
int a[100];
Expression Type "Decays" to
---------- ---- -----------
a int [100] int *
*a int n/a
&a int (*)[100] n/a
a[i] int n/a
&a[i] int * n/a
Again, the address of the array is the same as the address of the first element of the array, so &a
, a
, and &a[0]
will all yield the same address value (modulo any type conversions).
Adding 1 to a pointer yields the address of the next object of the pointed to type. IOW, if p
points to a 4-byte int
object, the result of p + 1
will be the address of the next 4-byte int
. If p
points to a 100-element array of 4-byte int
s, then p + 1
yields the address of the next 100-element array of int
.
The subscript operation a[i]
is defined as *(a + i)
- given the address a
, find the address of the i
'th object following a
and dereference the result.
This means that the value of *a
is the same as a[0]
- *a == *(a + 0) == a[0]
.
How does this apply to a 2D array, as in your example?
Given the declaration
int a[1][2];
the expression a
"decays" from type "1-element array of 2-element array of int
" (int [1][2]
) to "pointer to 2-element array of int
" (int (*)[2]
). The value of the expression a
is the address of the first element, but the first element has an array type itself. Thus, that value "decays" to a pointer to the first element of the subarray.
Here's a handy table to summarize:
int a[1][2];
Expression Type "Decays" to
---------- ---- -----------
a int [1][2] int (*)[2]
*a int [2] int *
&a int (*)[1][2] n/a
a[0] int [2] int *
*a[0] int n/a
&a[0] int (*)[2] n/a
a[0][0] int n/a
Again, &a
, a
, a[0]
, &a[0]
, and &a[0][0]
will all yield the same value, since the address of a[0][0]
is the same as the address of a[0]
which is the same as the address of a
.