• 1

According to GNU's documentation on Arrays of Variable Length, one can use the sizeof operator for determining the size of a variable length array that was passed into a function:

You can also use variable-length arrays as arguments to functions:

struct entry
tester (int len, char data[len][len])
  /* … */

The length of an array is computed once when the storage is allocated and is remembered for the scope of the array in case you access it with sizeof.

However, when trying this example with the complete code example below, the sizeof operator returns the size of the pointer, not the size of the allocated vla, as is expected based on the GNU snippet above.

I understand that passing arrays in C is akin to passing a pointer to the first element of the array, but since we're specifying the size in this case in the function signature, I would expect the behavior to mimic when using sizeof in the scope of where the array is declared.

I also realize I could use the len argument to figure out the size; but as a matter of convenience and understanding the GNU implementation I still think this is an interesting (if not important) question.

Thank you in advance to anyone who can provide insight into this!

// file: vla.c

void foo(int len, char data[len][len]) {
  printf("sizeof "foo" data: %lu
", sizeof(data));

int main(int argc, char * argv[]) {
  char data[argc][argc];
  printf("sizeof "main" data: %lu
", sizeof(data));
  foo(argc, data);

Compiled using:

gcc vla.c -o vla -std=c11

Called using:

./vla 2 3 4 5


sizeof "main" data: 25
sizeof "foo" data: 8


The size of the main data makes sense; argc is 5, therefore it's a (5 * 5 = 25) byte 2D array.

The size of the foo data was expected to also be 25, but is instead the size of the pointer. Seemingly the compiler is not using the fact that it knows the size of data within foo since it's part of the function signature.

An argument declared char data[len][len] is really char (*data)[len], a pointer to a VLA. There is no such thing as an actual array argument, and the first len in the declaration is meaningless. If you use sizeof *data, you will get back len though, since the pointed-to type is variably modified.

If you want both lens to be meaningful, you can pass a pointer-to-whole-array type rather than a pointer-to-first-element, declaring the argument char (*data)[len][len]. Now sizeof *data is len*len. But you'll need to use (*data)[i][j] to access it. You'll also need to use the & operator when calling the function:

int l = 42;
char array[l][l];
foo(l, &array);
  • 1
Reply Report