2012-04-12 78 views
6

我已经看了这些,他们不回答我的问题:GCC抱怨:可变大小的对象可能不被初始化

variable-sized object may not be initialized

C compile error: "Variable-sized object may not be initialized"

Error: Variable-sized object may not be initialized. But why?


我试图写一些相当便携的代码:

int main() 
{ 
    const int foo=13; 
    int bar[foo]={0}; 
    return 0; 
} 


使用作为c代码在编译时,我得到一个错误variable-sized object may not be initialized既:

  • GCC 4.3.4
  • ARM-Linux的gnueabi-GCC 4.4.5

如果我编译为cVS2008我得到一个略有不同error C2057: expected constant expression


据我所知,在这里,c代码编译器不承认const int foo=13;是真正的恒定;例如,我们可能有

void a(int fool) 
{  
    const int foo=fool; 
    int bar[foo]={0}; 
} 


我也意识到unlike the gcc compilersVS2008编译器有没有C99 variable-length arrays概念。而且这位MS显然没有提到任何未来的支持。


然而,cpp有两种GCCMS编译器代码编译是完全不同的/聪明?!


并且还什么我不明白关于GCCc代码编译为:


(注:在最后一种情况下,MSc代码编译失败,始终与int bar[foo]={0};

+0

在我的TDM-GCC 4.6.1上,最后一个例子没有**编译(再次使用“可变大小的对象不能被初始化”)。我也从来没有听说过由初始化列表初始化的VLA,这是否正确?望着它.. – Anthales 2012-04-12 18:29:32

+0

对于MS编译器问题的一部分,这不是唯一缺少的功能,它们只是不支持C99。自去年以来,甚至有更新版本的标准C11,所以他们现在缺少两个主要版本。 – 2012-04-12 18:45:30

+0

@ [anthales](http://stackoverflow.com/users/1250595/anthales),谢谢。嗯.. – violet313 2012-04-12 18:48:19

回答

10

C99§6.7.8初始化这样说:

的实体的类型来初始化应未知大小的阵列或即可变对象类型长度数组类型。

所以你的初始化无效C.

的唯一途径type a[size]是VLA是size是一个整型常量表达式(§6.7.5.2)。你有没有一个整数常量表达式,所以你有一个VLA:

如果大小不存在,数组类型是一个不完整的类型。如果大小是*而不是表达式,则数组类型是一个非指定大小的可变长度数组类型, 只能在具有函数原型范围的声明中使用,但这些数组仍然是完整类型的,即 。如果大小为整数常量表达式且元素类型具有已知的常量大小,则数组类型不是可变长度数组类型;否则,数组类型是可变长度数组类型。

部分6.6节/ 6 常量表达式将它们定义为:

一个整数常量表达式应具有整数型和应仅具有操作数 是整数常数,枚举常数,字符常数, sizeof 其结果为整数常量的表达式,以及浮点型变量的 即时操作数。使用整型常量表达式转换运算符只应将 将算术类型转换为整型,除了作为运算符sizeof的操作数的一部分。施加到一个整数变量

+0

好的。所以'foo + 1'不能是一个整型常量表达式,因为在编译时,即使它被声明为const,也不可能知道'foo'的值。所以这是我的gcc中的一个错误。 – violet313 2012-04-12 19:10:01

+1

有趣的是,'clang'支持'foo + 1'作为扩展:http://clang.llvm.org/docs/UsersManual.html#c_ext – Mat 2012-04-12 19:20:13

+0

它仍然唠叨我为什么在http://ideone.com/Br6cC ,数组'bar'被视为VLA。因为可以在编译时确定“foo”确实是一个整数常量。事实上,我很想知道什么样的汇编代码实际上是为'const int foo = 13;' – violet313 2012-04-12 19:55:38

1

其实,我的GCC(版本4.4.4),你的最后一个例子

int main() 
{ 
    const int foo=13; 
    int bar[foo+1]={0}; //wtF? 
    return 0; 
} 

不会编译,就像人们所期望的那样。您可能需要仔细检查您的工具链(以确认您没有在某处重新链接现有的'.o'),然后重试。

如果你发现它确实有效,这是我的gcc -v输出,也许你可以检测到配置上的差异,这可能会提供一些亮点。

Using built-in specs. 
Target: i686-redhat-linux 
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux 
Thread model: posix 
gcc version 4.4.4 20100630 (Red Hat 4.4.4-10) (GCC) 
+0

以及我得到[这个](http://pastebin.com/5TKnuStM)〜不知道我应该寻找什么样的tbh -looks,好像我可能正在犯另一个* debian squeeze稳定*效果 – violet313 2012-04-12 18:45:07

+0

我仍然没有真正明白为什么'cpp'工作,但'c'不能。我的意思是我可以看到'cpp'编译器具有所有必要的信息,不会引发错误。但是有没有一些特定的c标准*不是以相同的方式表现? – violet313 2012-04-12 18:50:52

+0

@ violet313,我的帖子是'cpp' _ does not_ work。显然你正在使用一个不同的编译器,或者甚至只是一个不同的'cpp'配置拷贝。如果它允许你编译,你正在使用的那个工作不正确;它是该编译器中的一个错误(如果你关心可移植性,即使编译器允许,也不应该使用这样的构造)。 – 2012-04-12 19:02:54

0

正如马特已经引用的标准,const限定符不计数为整数常量表达式。我们可能会问为什么?它看起来像整数常量一样无辜!

This may是因为const不是绝对的consts。你可能会通过指针改变它们的值,并且所有的编译器可能会这样做,如果它完全捕获了这样的任务,它会抛出一个警告,但是不能真正阻止你改变const的值。

PS:不要相信网上的编译器ideone.com等下面是一个愚蠢的runtime error它抛出了一个非常简单的C程序。

+0

ha。公平点,但我最初遇到了问题,然后编译我的* debian挤压测试* - 然后发现ideone编译器做了同样的事情 - 这似乎既方便,似乎使问题更相关 – violet313 2012-04-12 18:58:01