c ++数组初始化

c++ array initialization

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How to initialize an array in C
array initialization, is referencing a previous element ok?

我想知道在C/C++标准中这样做是否安全?

1
2
int a = 5;
int tab[] = { a , tab[0] + 1 , tab[1] };

它成功地编译和执行了GCC4.5和CLANG 2.9,但它总是真的吗?

打印此表将得到5 6 6。它在全局范围内初始化。

一般来说,C和C++都很有意思,但是我想在C++中使用它。


<子> C++ 03/C++ 11答案< /Sub >

不,不会的。

=的右侧,tab存在1,但如果它有自动存储时间,则它尚未初始化,因此您使用tab[0]tab[1]使用的是未初始化的变量。

如果tab在名称空间范围内(因此具有静态存储持续时间,并且已初始化为零),那么这是"安全的",但是您使用tab[0]不会给您提供5

很难提供这方面的标准参考资料,除了说明8.5"Initializers"中没有明确规定这一点的内容外,其他地方的规则也会补充其他内容。

1 [n3290: 3.3.2/1]: The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any) [..]


1
2
int a =5;
int tab[] = { a , tab[0] + 1 , tab[1] };

如果这些变量是在名称空间范围内声明的,那么它们是正常的,因为在名称空间范围内变量是零初始化的(由于静态初始化-请阅读本文了解详细信息)。

但是,如果它们在函数范围内声明,那么第二行调用未定义的行为,因为局部变量不是静态初始化的,这意味着tab[0]tab[1]是未初始化的,用于初始化数组。读取未初始化的变量会调用未定义的行为。


所以,现在我已经对你的问题进行了一些测试。

所有编译都是使用上面的示例代码执行的,使用以下方案:

1
$(GCC) -o a.out test.c -Wall -Wextra -pedantic -std=$(STD)

结果如下:

对于GCC = gcc,标准-std=c89; -std=iso9899:1990; -std=iso9899:199409; -std=gnu89导致出现警告:initializer element is not computable at load time,运行时行为不明确,意味着数组的第二和第三个值是随机垃圾。

标准-std=c99; std=iso9899:1999; -std=gnu99没有产生这种警告,但在运行时也显示出未定义的行为。

对于GCC = g++,标准-std=c++98; -std=gnu++98; -std=c++0x没有产生任何警告,代码按照您预期的方式工作,从而产生一个包含{5, 6, 6}值的数组。

然而,正如大多数人建议的那样,使用它可能是不明智的,因为您的代码在其他编译器上的行为可能不同,甚至在同一个编译器的其他版本上,这通常是一件坏事:)

希望有帮助。


在C99标准中,似乎可以保证成员的初始化顺序:

§6.7.8/17: Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union. In contrast, a designation causes the following initializer to begin initialization of the subobject described by the designator. Initialization then continues forward in order, beginning with the next subobject after that described by the designator.

但是正如@tomalak在注释中提到的那样,这并不能为操作提供完全的保证,因为编译器将首先评估所有参数,然后按照前面的顺序应用结果。也就是说,前一个报价没有在初始化tab[0]和评估用于初始化tab[1]的表达式tab[0]+1之间施加顺序(它只在初始化tab[0]tab[1]之间施加顺序)。

至于C++标准,既不在当前标准中,也不在即将到来的C++ 0x标准的FDIS中,似乎有一个特定的子句定义了初始化的顺序。唯一提到订购的是

§8.5.1/2 When an aggregate is initialized the initializer can contain an initializer-clause consisting of a brace-enclosed, comma-separated list of initializer-clauses for the members of the aggregate, written in increasing subscript or member order.

但这只与初始值设定项中的条目的写入顺序有关,而与实际计算方式无关。


是的-它可能会像你期望的那样工作。不,(你没有问,但是)不要用它,它没有逻辑,这是一个坏做法。