Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable length array in the middle of struct - why this C code is valid for gcc

Tags:

There is some strange code using VLA (Variable Length Arrays) which is treated as Valid C (C99, C11) by gcc 4.6:

$ cat a.c int main(int argc,char**argv) {   struct args_t{      int a;      int params[argc];        // << Wat?                         // VLA in the middle of some struct, between other fields      int b;   } args;    args.b=0;    for(args.a=0;args.a<argc;args.a++)   {     args.params[args.a]=argv[0][0];     args.b++;   }   return args.b; } 

This code compiled without warnings:

$ gcc-4.6 -Wall -std=c99 a.c && echo $? 0 $ ./a.out ; echo $? 1 $ ./a.out 2; echo $? 2 $ ./a.out 2 3; echo $? 3 

Same for -std=c1x:

$ gcc-4.6 -Wall -std=c1x a.c && echo $? 0 

But this does not work with Intel C Compiler or with Clang+LLVM:

$ icc a.c -o a.icc a.c(5): warning #1361: variable-length array field type will be treated as zero-length array field type        int params[argc];                   ^ $ ./a.icc; echo $? 47  $ clang a.c -o a.clang a.c:5:10: error: fields must have a constant size: 'variable length array in structure' extension will never be supported      int params[argc];          ^ 1 error generated. 

So:

  1. Why is this considered valid by GCC?
  2. If it is an extension of GCC, where is it described?
  3. Is it valid in C99 and C11 ISO Standards?
like image 360
osgx Avatar asked Jan 31 '13 15:01

osgx


People also ask

Does C allow variable length arrays?

C supports variable sized arrays from C99 standard. For example, the below program compiles and runs fine in C. NOTE: In C99 or C11 standards, there is feature called flexible array members, which works same as the above.

Why are variable length arrays bad in C?

The biggest problem is that one can not even check for failure as they could with the slightly more verbose malloc'd memory. Assumptions in the size of an array could be broken two years after writing perfectly legal C using VLAs, leading to possibly very difficult to find issues in the code.

Does C support VLA?

Allocation. The GNU C Compiler allocates memory for VLAs with automatic storage duration on the stack. This is the faster and more straightforward option compared to heap-allocation, and is used by most compilers. VLAs can also be allocated on the heap and internally accessed using a pointer to this block.

Can we declare an array with size 0 in C?

6.18 Arrays of Length Zero. Declaring zero-length arrays is allowed in GNU C as an extension.


2 Answers

GCC does not allow it, compile with -std=c99 -pedantic-errors. A VLA inside a struct is apparently a (poorly documented) non-standard GNU C feature. See this.

like image 119
Lundin Avatar answered Sep 26 '22 02:09

Lundin


The standard is pretty clear that VLAs are not allowed in a struct:

6.7.2.1 Structure and union specifiers

9 - A member of a structure or union may have any complete object type other than a variably modified type. [...]

Variably modified types are (as you might expect) those derived from a variable length array (e.g. by adding array dimensions or cv qualifiers):

6.7.6 Declarators

3 - [...] If, in the nested sequence of declarators in a full declarator, there is a declarator specifying a variable length array type, the type specified by the full declarator is said to be variably modified. Furthermore, any type derived by declarator type derivation from a variably modified type is itself variably modified.

like image 20
ecatmur Avatar answered Sep 25 '22 02:09

ecatmur