简体   繁体   中英

What is the difference between the parameter c[a][b] and c[][2]

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:

  • In the latter declaration, the compiler knows the array has two elements, and it can generate code with 2 built into it. In the former declaration, the compiler does not know from the declaration alone how big the array is. Therefore, when it needs the size of the array for some reason, it must generate code that computes array element locations using 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.
  • In the latter declaration, the C standard is unclear about whether 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM