22
votes

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?
3
+1; in a recent question, someone posted an actual program that exploited this feature. I was surprised that it worked.Fred Foo
Documented in GCC in "6.19 Arrays of Variable Length" in one sentence and one example only: "As an extension, GCC accepts variable-length arrays as a member of a structure or a union. void foo(int n) { struct S { int x[n]; }; }". Documentation updated in gcc 4.9: gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Variable-Length.html github.com/gcc-mirror/gcc/commit/… (svn 208836) PR c/37428 at 2014-03-26 by Marek Polacek of RedHat; gcc.gnu.org/bugzilla/show_bug.cgi?id=37428 "GNU VLA-in-structure extension is undocumented" (2008-09)osgx

3 Answers

9
votes

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.

4
votes

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.

-2
votes

The authors of the C89 Standard recognized that many implementations implemented useful features which might be impractical on other implementations, and recognized that as a good thing. The Standard was intended as a minimum set of requirements for implementations; it was never intended to discourage implementations from providing features beyond that.

The Standard requires that if a conforming implementation allows a variable-length array to be declared within a structure defined at block scope, it must either document such behavior as an extension or issue a diagnostic when code contains such a declaration. Since an implementation would be free to process the code however it likes after issuing such a diagnostic, whether or not it documents an extension, the requirement to document extensions can only be meaningfully applied to extensions which do not generate diagnostics. That in turn would suggest that such things must be allowable.

The Standard does require that extensions not adversely affect the behavior of any Strictly Conforming programs, but since no such program could contain a VLA declaration within a structure that requirement is not a problem here.