What is the reason, that the first index in the function void transposeMatrix(int a[][arraySize])
is empty?
-
Because arrays decay to pointers. – Osiris Jul 19 '18 at 13:31
-
7Because the function needs only the second dimension to correctly calculate the location of `a[i][j]`. – Eugene Sh. Jul 19 '18 at 13:35
-
Presumably, the function has some other means to determine the number of rows. – Ian Abbott Jul 19 '18 at 14:02
-
See also [What is the purpose of static keyword in array parameter of function](https://stackoverflow.com/q/3430315/2410359). – chux - Reinstate Monica Jul 19 '18 at 14:32
-
Note that the first dimension is not the 'row size'; it is the number of rows. The row size is the second dimension of a 2D array, and that must be provided. And if you're dealing with 3D or higher-dimensional arrays, all sizes except the first must be provided, one way or another (the 'another' being using VLA notation). – Jonathan Leffler Jul 19 '18 at 15:07
-
@saddam We? or you? – 0___________ Jul 19 '18 at 15:23
2 Answers
Because what transposeMatrix
receives really isn't a 2D array, but rather a pointer to a 1D array.
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
" 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.
If you declare an array as
int arr[N][M];
and pass it to a function
void foo( arr );
then the expression arr
is converted from type "N-element array of M-element array of int
" to "pointer to M-element array of int
" (int (*)[M]
).
In a function parameter declaration, T a[N]
and T a[]
are "adjusted" to T *a
- IOW, all three declare a
as a pointer to T
(this is only true for function parameter declarations).
Thus,
void transposeMatrix(int a[][arraySize])
is equivalent to
void transposeMatrix(int (*a)[arraySize])
Using a[][M]
rather than (*a)[M]
is a notational convenience (similar to using p->m
instead of (*p).m
for accessing struct
and union
members through pointers).
Because of how array indexing works, you can index into a
like any other 2D array. Remember that the subscript operation a[i]
is defined as *(a + i)
- given a starting address a
, find the address of the i
'th element (not byte) following a
and dereference the result. So:
(*a)[i] == (*(a + 0))[i] == (a[0])[i] == a[0][i]
meaning
(*(a + j))[i] == (a[j])[i] == a[j][i]

- 119,563
- 19
- 122
- 198
-
How is the automatic conversion of an array to a pointer relevant? Suppose arrays were not automatically converted to pointers. Then, when an array `a` is passed to a function, it would have to be passed by some other mechanism, such as by reference or by copy, although other methods are possible. If it were a very small array, for example, such as `char[n][2]` for n≤4, it could be passed entirely in an eight-byte register, as some ABIs do for small structs. And the called routine would not need to know n. So it is not conversion to a pointer that enables the first dimension to be omitted. – Eric Postpischil Jul 20 '18 at 02:49
When you have an array a
of n
objects of type foo
, the compiler can calculate the location of element a[i]
by adding i
times the size of a foo
object to the starting address of a
.
Note that this calculation involves only the size of foo
and the subscript i
. It does not involve the number of elements n
. The compiler does not need to know the number of elements in order to calculate where an element is.
You would need to know the number of elements in an array to avoid going beyond the end of an array. However, in C, it is not the compiler’s job to guard against going beyond the end of the array. The author of the function is responsible for doing that. So, for this purpose, the compiler does not need to know how many elements are in an array.
Now suppose each foo
object is itself an array of m
objects of type bar
. The compiler does need to know the size of a foo
object. How big is a foo
? Since a foo
is an array of m
objects of type bar
, its size is m
times the size of bar
. So, to know how big a foo
is, the compiler needs to know how many elements in in the array.
Thus, when passing an int a[FirstDimension][SecondDimension]
, the compiler does not need to know FirstDimension
but does need to know SecondDimension
.

- 195,579
- 13
- 168
- 312