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
#include <stdio.h>
void foo(int len, char data[len][len]) {
printf("sizeof \"foo\" data: %lu\n", sizeof(data));
}
int main(int argc, char * argv[]) {
char data[argc][argc];
printf("sizeof \"main\" data: %lu\n", sizeof(data));
foo(argc, data);
}
Compiled using:
gcc vla.c -o vla -std=c11
Called using:
./vla 2 3 4 5
Output:
sizeof "main" data: 25
sizeof "foo" data: 8
Analysis:
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 len
s 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);