这些三维数组在C中合法吗?

时间:2017-07-27 19:27:47

标签: c arrays

我教授的期末考试主要包括非常棘手的语法。例如,他的一些问题就像是“使用指针1打印字母k而不使用括号。幸运的是它是开放的书。

所以有一个问题是:

int a[2][2][2] = {{5,6}, {7,8}, {9,10}, {11,12}}; 

写一个打印出“7910”的printf语句。 不使用方括号使用指针。

起初,我认为这是一个错字或非法阵列。我以为数组应该从左边的第三个数组停止。

我写道:

printf("%d%d%d\n",*(*(a+1)+1)),*(*(a+2)),*(*(a+2)));

我把它放了,因为如果数组是

int a[2][2] = {{7,8},{11,12}};

类似的语法可行。

这是一个错字吗?如果没有,那么正确的语法是什么?

2 个答案:

答案 0 :(得分:5)

在大多数情况下,编译器会将上述初始化解析为

int a[2][2][2] = { { {5,6}, {7,8} }, 
                   { {9,10}, {11,12} }
                 };   

如果您将其写为

,这也会有效
int a[2][2][2] = {5, 6, 7, 8, 9, 10, 11, 12};   

但这确实不是一个好习惯。

C标准说了这件事 §6.7.9(P17):

  

当没有指定时,根据当前对象的类型按顺序初始化当前对象的子对象:增加下标顺序的数组元素,声明顺序中的结构成员,以及union 149)。 [...]

p26

  

示例3声明

int y[4][3] = {
    { 1, 3, 5 },
    { 2, 4, 6 },
    { 3, 5, 7 },
};
     

是一个包含完全括号初始化的定义:135初始化y的第一行(数组对象y[0]) ,即y[0][0]y[0][1]y[0][2]。同样,接下来的两行初始化y[1]y[2]。初始化程序提前结束,因此y[3]初始化为零。

可以达到同样的效果
int y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5, 7
};
     

y[0]的初始化程序不以左括号开头,因此使用列表中的三个项目。同样地,接下来的三个是针对y[1]y[2]连续拍摄的。

答案 1 :(得分:1)

这一行:

int a[2][2][2] = {{5,6}, {7,8}, {9,10}, {11,12}}; 

无效C且编译器应报告诊断消息。

根据C11 N1570,§6.7.9/ 20 初始化

  

如果聚合或联合包含元素或成员   聚合或联合,这些规则递归地应用于   分包或包含工会。 如果是初始化程序   subaggregate 或包含union 以左括号开头   由该支撑包围的初始化器及其匹配的右支撑   初始化子聚合的元素或成员或   包含联盟。

问题是{{5,6}, {7,8}, {9,10}, {11,12}}尝试初始化最外层数组对象的四个元素(即a表示数组数组int)的数组,虽然它的大小明确地表示为两个:

int a[2][2][2] = {{5,6}, {7,8}, {9,10}, {11,12}};
      |           |      |      |       |
      |           |      |      |       |
      -----------------------------------

这是违反约束的行为,如§6.7.9/ 2:

  

初始化程序不应尝试为对象提供值   包含在正在初始化的实体中。

如果省略第一个尺寸,有效,如下所示:

int a[][2][2] = {{5,6}, {7,8}, {9,10}, {11,12}};

实际上与:

相同
int a[4][2][2] = {
    {
        {5, 6},
        {0, 0}
    },
    {
        {7, 8},
        {0, 0}
    },
    {
        {9, 10},
        {0, 0}
    },
    {
        {11, 12},
        {0, 0}
    }  
};

请注意,您可以将其初始化为:

int a[2][2][2] = {5, 6, 7, 8, 9, 10, 11, 12}; // legal, but not advisable

甚至:

int a[2][2][2] = {{5, 6, 7, 8}, {9, 10, 11, 12}}; // bad style

上述§6.7.9/ 20的剩余句子允许这样做:

  

否则,只会考虑列表中足够的初始值设定项   对于子聚合的元素或成员或者第一个成员   包含的联盟;任何剩余的初始化程序都要进行初始化   当前聚合的下一个元素或成员   subaggregate或contains union是其中的一部分。