3

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.

4
  • 2
    I suspect you'll find that the normal rules apply to function arguments (you get the size of a pointer). What the text you quote is mainly referring to is arrays defined inside a function (you can't define variable size arrays at global scope). Having said that, the manual reference definitely implies that what you're doing should work. Commented Aug 3, 2018 at 4:53
  • 2
    Aside: Better to use "%zu" with size_t --> printf("%zu\n", sizeof(...)); Commented Aug 3, 2018 at 4:57
  • After some frenzied cogitation, I think that storage isn't allocated when you call a function. I think the paragraph after the sample code is a non sequitur. But it isn't obvious from what the manual says. Commented Aug 3, 2018 at 5:03
  • @JonathanLeffler, I agree with that assessment. Also thanks for the formatting fixes, much appreciated! Commented Aug 3, 2018 at 5:15

1 Answer 1

5

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);
Sign up to request clarification or add additional context in comments.

2 Comments

It should be noted the page OP refers to is poorly written. It says “You can also use variable-lenth arrays as arguments to functions” and gives the example of an argument declared char data[len][len]. This might be technically correct, as an array can be “used” as an argument for this function, but it is nonetheless converted to a pointer, and the wording is misleading, perhaps suggesting GCC is supporting some C expansion or deviation…
… The type char data[len][len] is likely intended to make the point that the second dimension is variable-length. The wording should likely have said that variable-length arrays may be used as parts of types passed to functions, using an example such as char (*data)[len].

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.