可能重复:
array initialization, is referencing a previous element ok?
我想知道在c/c++标准中进行这样的初始化是否安全:
int a = 5;
int tab[] = { a , tab[0] + 1 , tab[1] };它成功地用gcc 4.5和clang 2.9编译和执行,但它会永远是真的吗?
打印这张表给5 6 6。它在全局范围内初始化。
一般来说,它在c++和c中都很有趣,但是我想在c++中使用它:)
发布于 2011-09-11 15:10:03
在C99标准中,似乎保证了成员的初始化顺序:
§6.7.8/17:每个大括号括起来的初始化程序列表都有一个关联的当前对象。当没有指定时,根据当前对象的类型对当前对象的次对象进行初始化:数组元素以增加下标顺序,结构成员按声明顺序,以及联合的第一个命名成员。相反,指定会导致下面的初始化器开始初始化由指示符描述的子对象。然后继续按顺序进行初始化,从下一个子对象开始,后面是由指示符描述的子对象。
但是正如@Tomalak在注释中提到的那样,这并不能为操作提供充分的保证,因为编译器将首先计算所有参数,然后按照前面的顺序应用结果。也就是说,前面的引号并没有在tab[0]的初始化和用于初始化tab[1]的表达式tab[0]+1的计算之间强加一个顺序(它只是在tab[0]和tab[1]的初始化之间施加了一个顺序)。
在C++标准中,当前标准和即将发布的C++0x标准的FDIS似乎都没有一个特定的子句来定义初始化的执行顺序。点菜的唯一来源是
§8.5.1/2当初始化聚合被初始化时,初始化器可以包含一个初始化器-子句,由一个大括号括起来的、逗号分隔的初始化器-子句组成,用于聚合成员的初始化-子句,以增加下标或成员顺序写入。
但这只与写入初始化程序中的条目的顺序有关,而与实际计算它的方式无关。
发布于 2011-09-11 13:35:28
int a =5;
int tab[] = { a , tab[0] + 1 , tab[1] };如果这些变量是在名称空间范围声明的,那么它们就可以了,因为在名称空间范围,变量是零初始化的(因为静态初始化-读取详细信息的this )。
但是,如果它们在函数作用域中声明,那么第二行调用未定义的行为,因为局部变量不是静态初始化的,这意味着tab[0]和tab[1]未初始化,用于初始化数组。读取未初始化的变量会调用未定义的行为。
发布于 2011-09-11 16:39:59
所以,现在我已经对你的问题做了几个测试。
所有编译都是使用上面的示例代码执行的,使用以下方案:
$(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}的数组。
然而,正如大多数人所建议的那样,使用这种方法可能是不明智的,因为您的代码在其他编译器上的行为可能有所不同,甚至可能是同一编译器的其他版本,这通常是一件坏事:)
希望能帮上忙。
https://stackoverflow.com/questions/7378492
复制相似问题