struct中间的可变长度数组 - 为什么这个C代码对gcc有效

osg*_*sgx 22 c gcc c99 variable-length-array c11

使用VLA(可变长度数组)有一些奇怪的代码,它被gcc 4.6视为有效C(C99,C11):

$ 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;
}
Run Code Online (Sandbox Code Playgroud)

此代码编译时没有警告:

$ 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
Run Code Online (Sandbox Code Playgroud)

同样的-std=c1x:

$ gcc-4.6 -Wall -std=c1x a.c && echo $?
0
Run Code Online (Sandbox Code Playgroud)

但这不适用于英特尔C编译器或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.
Run Code Online (Sandbox Code Playgroud)

所以:

  1. 为什么GCC认为这有效?
  2. 如果它是GCC的扩展,它在哪里描述?
  3. 它在C99和C11 ISO标准中有效吗?

Lun*_*din 9

GCC不允许它,编译-std=c99 -pedantic-errors.结构中的VLA显然是一个(文档记录很少)的非标准GNU C特性.看到这个.

  • @osgx:`-pedantic`是要使用的标志,如果你想编译严格遵守标准的代码.这面旗帜是众所周知的,有记载的特征. (14认同)
  • 曾经使用过`-pedantic-errors`的人?为什么这个扩展如此隐藏?没有任何gcc用户会知道此代码不正确,因为默认gcc模式中没有任何警告. (3认同)
  • @osgx:`-pedantic`是众所周知的; 它导致gcc至少警告违反标准.`-pedantic-errors`可能不太为人所知; 它就像`-pedantic`,除了任何违规被视为致命错误.关于gcc最重要的事情之一是默认情况下它不是符合标准的C编译器.http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Standards.html#Standards (3认同)
  • @osgx GCC最大的缺陷之一确实是它没有默认为标准C,而是默认为"GNU goo".如果您关注一致性和可移植性,则应始终使用-pedantic和-Wall进行编译.我没试过,但是 - 也许也会抱怨VLA. (2认同)