In the context of a function parameter declaration, T a[]
and T a[N]
are synonymous with T *a
; a
is a pointer type, not an array type, regardless of whether you use []
or [N]
or *
.
Chapter and verse:
6.7.6.3 Function declarators (including prototypes)
...
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [
and ]
of the
array type derivation. If the keyword static
also appears within the [
and ]
of the
array type derivation, then for each call to the function, the value of the corresponding
actual argument shall provide access to the first element of an array with at least as many
elements as specified by the size expression.
Why would that be the case? This is why:
6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof
operator, the _Alignof
operator, or the
unary &
operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue. If the array object has
register
storage class, the behavior is undefined.
In the call to function
, the expression array
has type "5-element array of int
"; by the rule in 6.3.2.1/3, it is converted ("decays") to an expression of type "pointer to int
", and its value is the address of the first element (&array[0]
); this pointer value is what gets passed to function
.
If array
had been declared as int array[5][5]
, then the expression array
would be converted from "5-element array of 5-element array of int
" to "pointer to 5-element array of int
", or int (*)[5]
, and your function declaration would look like
void function(int (*array)[5], int size)
which could also be written as
void function(int array[][5], int size)
or
void function(int array[5][5], int size)
Note that in this case, the size of the outer dimension is not optional; it must be specified so that the compiler knows the size of the type being pointed to.