Given the following two declarations, what is the difference?
int foo ( int a, int b, int c[a][b] ) {
int foo ( int a, int b, int c[][2] ) {
I understand the top statement is a "Variable Length Array" (VLA), but I'm not sure I understand what that means. Both of these produce the same result.
int foo ( int a, int b, int c[a][b] ) {
for ( int *p = c[0]; p <= &(c[a-1][b-1]); p++ ) {
*p = 0;
}
}
vs..
int foo ( int a, int b, int c[][2] ) {
for ( int *p = c[0]; p <= &(c[a-1][b-1]); p++ ) {
*p = 0;
}
}
This is my main
,
int main () {
int m[2][2] = { {1,2},{3,4} };
foo(2,2,m);
printf( "%s %d %d %d %d", "foo", m[0][0],m[0][1],m[1][0],m[1][1] );
return 0;
}
I can not find any resource that sufficiently explains what's going on here.
In int foo ( int a, int b, int c[a][b] )
, the parameter c
is declared to be a pointer to an array of b
int
. That is, it points to an array of int
in which the number of elements is b
.
In int foo ( int a, int b, int c[][2] )
, the parameter c
is declared to be a pointer to an array of 2 int
.
When b
is two, these declarations are identical for practical purposes. Technical differences include:
b
at run-time, unless it is able to deduce the value of b
at compile time by looking at other code in the program. a
is evaluated or not. That does not matter in this case where a
is a simple object, but you are also allowed to put expressions there, and expressions can cause observable effects such as printing output. I have seen a C implementation that did evaluate that dimension and a C implementation that did not. I have never seen a real-world program where this mattered. When a parameter declaration appears in array form, the first dimension is automatically adjusted to be a pointer. This is because C passes arrays only by pointing to the first element, not by passing the value of the entire array as it does with non-array parameters. So a parameter declared as int foo[a][b][c][d]
is adjusted to int (*foo)[b][c][d]
. Only the first dimension is adjusted because the pointer does point to actual arrays in memory, so the other dimensions are there; they are not pointers. Allowing parameters to be declared this way is merely a notational convenience.
In both cases, c
is a pointer to an array of int
. Commonly, such a parameter points to a first array of int
, and that array is followed by another, and another, and so on, to form an array of arrays of int
. This is went the second dimension, b
or 2, matters. The compiler needs that dimension to know how big the arrays of int
are, so that, when the source code accesses arrays beyond the first one, the compiler is able to calculate their addresses by multiplying the size of each array of int
by the array index. In the case of 2
, the array size is constant, and the compiler should generate multiplication by a constant. In the case of b
, the compiler may have to generate code that fetches b
from a register or somewhere and multiplies by that.
If foo
is written to always take an array of arrays of 2 int
, then you should declare the parameter with 2
. If foo
is written to take arrays of whatever size the caller requests, then you should declare the parameter with b
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.