gcc抱怨:可能无法初始化变量大小的对象

我看过这些,他们没有回答我的问题:

可能无法初始化可变大小的对象

C编译错误:“可能无法初始化可变大小的对象”

错误:可能无法初始化可变大小的对象。 但为什么?

我正在尝试编写一些相当便携的c代码:

 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

如果我在VS2008中将其编译为c ,我会得到一个稍微不同的error C2057: expected constant expression

我明白在这里, c代码编译器无法识别const int foo=13; 真实地保持不变; 例如我们可能有

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

我也意识到, 与gcc编译器不同 , VS2008编译器没有C99可变长度数组的概念。 那个MS显然没有提到任何未来的支持。

然而,使用gccMS编译器的cpp代码编译是完全不同/更聪明的?

  • 这无法编译
  • 但这会编译

关于gcc c代码编译器我还不明白的是:

  • 因为这段代码 可以编译,
  • 为什么这段代码 不能编译..
  • 然而这段代码 确实编译了?

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

C99§6.7.8 初始化说明:

要初始化的实体的类型应该是未知大小的数组或不是可变长度数组类型的对象类型。

所以你的初始化是无效的C.

type a[size] 不是 VLA的唯一方法是将size作为整数常量表达式 (§6.7.5.2)。 你有什么不是一个整数常量表达式,所以你有一个VLA:

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

Part§6.6/ 6 常量表达式将它们定义为:

整数常量表达式应具有整数类型,并且只能具有整数常量的操作数,枚举常量,字符常量,结果为整数常量的sizeof表达式,以及作为强制转换的直接操作数的浮点常量。 整数常量表达式中的转换运算符只能将算术类型转换为整数类型,除非作为sizeof运算符的操作数的一部分。

实际上,对于我的gcc(版本4.4.4),你的最后一个例子

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

没有编译,正如人们所期望的那样。 您可能想要仔细检查您的工具链(以validation您没有在某处重新链接现有的“.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) 

由于Matt已经引用了标准,因此应用于整数变量的const限定符不计为整数常量表达式 。 我们可能想知道为什么 它看起来像整数常量一样无辜!

可能是因为const不是绝对的。 您可以通过指针改变它们的值,并且编译器可能会执行所有操作,如果它捕获了这样的赋值,则会发出警告,但是无法阻止您更改const值。

PS: 不要相信像ideone.com等在线编译器 。这是一个非常简单的C程序抛出的一个愚蠢的运行时错误 。