这个问题在这里已有答案:
像这样初始化数组中的某些元素是否安全?
const char *str_array[50] = {
[0] = "str_0",
[10] = "str_10",
[24] = "str_24",
[45] = "str_45",
};
我可以依赖正确初始化的数组的其他元素吗?
问题中显示的初始化是安全的,未使用指定的初始化程序专门初始化的元素(在此上下文中)初始化为NULL。通常,未初始化的元素初始化与初始化相同类型的静态变量相同,这是“零”主题的一些变化。
C标准(ISO / IEC 9899:2011)的相关部分是§6.7.9 Initialization,特别是¶19:
初始化应在初始化器列表顺序中进行,每个初始化器为特定子对象提供,覆盖任何先前列出的同一子对象的初始化器; 151)未明确初始化的所有子对象应与具有静态存储持续时间的对象隐式初始化。
151)子对象的任何初始化程序被覆盖并因此不用于初始化该子对象可能根本不会被评估。
评论中有一个反驳:
如果我希望其他元素设置为相同的默认值怎么办?
不幸的是,您必须选择NULL(在这种情况下;在一般情况下为零)作为默认值。你在标准C中没有任何其他选择(不像复杂的现代语言,哦,我不知道 - 让我们想到Fortran 66)。标准C中没有办法重复初始化器而不是多次写入。
GCC有一个扩展,允许您这样做(在GCC手册中记录的标题为Designated Initializers的部分记录了标准行为和非标准行为)。使用GNU扩展,您可以编写:
const char *str_array[50] = {
[1 ... 49] = "empty string", // GCC extension
[0] = "str_0",
[10] = "str_10",
[24] = "str_24",
[45] = "str_45",
};
注意,可以为单元格指定两个初始值设定项(例如10,24,45 - 另一个是通过重复的初始化程序);最后一个提到胜利。还要注意将...
与1
(和45
)隔开的空间;这是至关重要的,因为'最大的蒙克规则'意味着[1...45]
将被标记为[
,1.
,.
,.45
,]
,其中浮点数不是想要的。
是的,这很安全。
见N1570第6.7.9节。
第19段,讨论初始化列表:
...所有未明确初始化的子对象应与具有静态存储持续时间的对象隐式初始化。
第10段:
如果未显式初始化具有自动存储持续时间的对象,则其值不确定。如果未显式初始化具有静态或线程存储持续时间的对象,则:
- 如果它有指针类型,则将其初始化为空指针;
- 如果它有算术类型,则初始化为(正或无符号)零; - 如果它是一个聚合,则根据这些规则初始化(递归)每个成员,并将任何填充初始化为零比特;
- 如果它是一个联合,则根据这些规则初始化(递归)第一个命名成员,并将任何填充初始化为零位;