Except when it is the operand of the sizeof
, _Alignof
, 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
" will be converted ("decay") to an expression of type "pointer to T
" and the value of the expression will be the address of the first element of the array.
When you pass an array expression as a function argument, what the function actually receives is a pointer value:
void foo( T *a ) // equivalent to T a[] and T a[N]
{
...
}
int main( void )
{
T arr[N];
...
foo( arr );
...
}
As a "convenience" C allows you to use array notation for a function parameter declaration, but be aware it will be "adjusted" to be a pointer declaration because the parameter is a pointer value, not an array - T a[N]
and T a[]
will be interpreted as T *a
. Note that this is only true in a function parameter declaration, not a regular variable declaration.
Now, just for giggles, replace T
with the array type double [M]
. So instead of being an N-element array of T
, arr
is now an N-element array of M-element arrays of double
:
int main( void )
{
double arr[N][M];
...
foo( arr );
...
}
In the call to foo
, the expression arr
"decays" from type "N-element array of M-element arrays of double
" to "pointer to M-element array of double
", or double (*)[M]
. So our declaration of foo
looks like this:
void foo( double (*a)[M] ) // equivalent to double a[][M] and double a[N][M]
{
...
}
And this is why the two seemingly different declarations are equivalent - in the context of a function parameter declaration, double a[][M]
is interpreted as double (*a)[M]
. Again, this is only true for function parameter declarations, not regular variable declarations.