初始化多维数组时,编译器如何解释不完整的初始化列表?

海牙叶

我一直试图追溯一些编译器应用于不完整的多维初始化列表的逻辑。说有一个3d这样数组:

char list[3][3][3];

如果我用这样的单个元素初始化它:

char list[3][3][3] = {1}

一切都按预期进行,编译器设置list[0][0][0]为1,其余元素保持未初始化状态,并保留0或一些随机值。如果我尝试应用这样的列表,事情就会变得一团糟:

char list[3][3][3] = {{1, 2}, 3}

我希望元素list[0][1][0]保留值3。相反,它存储在中list[1][0][0]换句话说,如果为3维数组指定2维初始化列表,则不切换第二维数组,而是切换最外面的数组。

这也是有趣的是,如果我喜欢指定初始化列表{3, {1, 2}},编译器为多余元素的警告,但仍编译代码,存储31在位置[0][0][0][0][0][1]不存储2任何地方(至少我没有找到它)。

问题是:编译器如何解释不完整的多维初始化列表?我很高兴获得有关使用此类初始化列表初始化多维数组的逻辑的某种评论。

詹斯

在C语言中,根据Standard,如果初始化化合物的任何元素,则所有未明确分配的其余元素也会被初始化以及是否分配为0(即对于指针,其为NULL,对于浮点数为0.0)。这是递归适用的,因此适用于struct内的数组数组和struct等。

元素从内存中的低位到高位分配,其中数组的最右边索引变化最快。因此,对于a [] [],序列为a [0] [0],a [0] [1],... a [1] [0],a [1] [1],...

如果不使用大括号,情况会有些复杂。从C99,6.7.8初始化

  1. 否则,具有聚合或联合类型的对象的初始化器应为元素或命名成员的括号括起来的初始化器列表。
  2. 每个用大括号括起来的初始化器列表都有一个关联的当前对象。如果没有指定,则根据当前对象的类型按顺序初始化当前对象的子对象:下标顺序递增的数组元素,声明顺序的结构成员以及并集的第一个命名成员。相反,指定使随后的初始化程序开始对由指定程序描述的子对象进行初始化。然后从指定者描述的下一个子对象开始按顺序继续初始化。
  3. 每个指示符列表均以与最接近的括号对关联的当前对象开始其描述。指示符列表中的每个项目(按顺序)指定其当前对象的特定成员,并将当前对象更改为下一个指示符(如果有)为其成员。在指定符列表末尾产生的当前对象是要由以下初始化程序初始化的子对象。
  4. 初始化应以初始化程序列表的顺序进行,为特定子对象提供的每个初始化程序都将覆盖先前为同一子对象列出的所有初始化程序。所有未明确初始化的子对象都应与具有静态存储持续时间的对象隐式初始化。
  5. 如果聚合或联合包含作为聚合或联合的元素或成员,则这些规则将递归应用于子聚合或包含的联合。如果子集合或包含的并集的初始化程序以左括号开头,则该括号括起来的初始化程序及其匹配的右括号将初始化子集合或包含的并集的元素或成员。否则,仅使用列表中足够的初始化程序来考虑子聚合的元素或成员或所包含的并集的第一个成员;剩下的所有初始化程序都将初始化当前子聚合或所包含的并集所属的聚合的下一个元素或成员。
  6. 如果用大括号括起来的列表中的初始化程序少于集合中的元素或成员,或者用于初始化已知大小的数组的字符串文字中的字符少于该数组中的元素,则该集合的其余部分应与具有静态存储持续时间的对象隐式初始化相同。
  7. 如果初始化未知大小的数组,则其大小由具有显式初始化程序的最大索引元素确定。在其初始化程序列表的末尾,数组不再具有不完整的类型。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章