在初始化C/C++多维数组时省略大小

Oma*_*man 26 c c++ initialization multidimensional-array

我对C/C++编译器的了解是,它们在初始化多维数组时忽略了内部括号.

所以,你不能这样做:

int myArray[][] = { { 2, 3 }, { 4, 5 }, { 4, 1 } };
Run Code Online (Sandbox Code Playgroud)

因为编译器会完全看到它

int myArray[][] = { 2, 3, 4, 5, 4, 1 };
Run Code Online (Sandbox Code Playgroud)

现在它不知道它是6*1,3*2,2*3,1*6,还是其他东西(因为这可能是部分初始化列表,不一定完整).

我的问题是,为什么这在许多编译器中都有效?

int myArray[][2] = { { 2 }, { 4, 5 }, { 4, 1 } };
Run Code Online (Sandbox Code Playgroud)

编译器"直观地"将其视为:

int myArray[][2] = { { 2, 0 }, { 4, 5 }, { 4, 1 } };
Run Code Online (Sandbox Code Playgroud)

这意味着它不会忽略大括号.到目前为止,我已经在三个不同的编译器上尝试了它并且都工作了.

我希望答案是"这只是编译器依赖".我无法访问该标准,因此请提供标准的答案.我不需要直觉,我有我的.

use*_*109 10

尝试2.

以下内容来自K&R的"The C Programming Language"第A8.7节,第2版,第219,220页

聚合是结构或数组.如果聚合包含聚合类型的成员,则初始化规则将递归应用.可以在初始化中省略大括号,如下所示:如果聚合的成员的初始化程序本身是聚合,以左括号开头,则后续的以逗号分隔的初始化程序列表初始化子聚合的成员; 如果有比成员更多的初始化者是错误的.但是,如果子集合的初始化程序不以左括号开头,那么只有列表中的足够元素才能考虑子集合的成员; 任何剩余的成员都要初始化子聚合所属的聚合的下一个成员.例如,

 int x[] = { 1, 3, 5 }; 
Run Code Online (Sandbox Code Playgroud)

声明并将x初始化为具有成员的1维数组,因为没有指定大小并且有三个初始值设定项.

因此,给定这一行

int myArray[][2] = { { 2 }, { 4, 5 }, { 4, 1 } };
Run Code Online (Sandbox Code Playgroud)

编译器将递归地初始化数组,注意每个子数组以左括号开始并且不超过所需数量的初始化器,并将计算子数组的数量以确定数组的第一个维度.

以下内容来自K&R的第2版,第220页的"C编程语言"A8.7节

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

is equivalent to

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

Note that in both cases, the fourth row of the array will be initialized 
with zero, since not enough initializers were specified.

float y[4][3] = { 
    { 1 }, { 2 }, { 3 }, { 4 } 
};

initializes the first column of y and leaves the rest 0.
Run Code Online (Sandbox Code Playgroud)

所以编译器不会忽略内部大括号.但是,如果按顺序指定所有初始化程序而没有间隙,则内括号是可选的.如果您不想指定一组完整的初始值设定项,则使用内括号可以更好地控制初始化.


use*_*109 6

以下内容来自K&R的第2版,第220页的"The C Programming Language"的A8.7

float y[4][3] = {
    { 1, 3, 5 },    
    { 2, 4, 6 },
    { 3, 5, 7 }
};
Run Code Online (Sandbox Code Playgroud)

相当于

float y[4][3] = {
   1, 3, 5, 2, 4, 6, 3, 5, 7 
};
Run Code Online (Sandbox Code Playgroud)

请注意,在这两种情况下,数组的第四行将初始化为零,因为没有指定足够的初始值设定项.

float y[4][3] = { 
    { 1 }, { 2 }, { 3 }, { 4 } 
};
Run Code Online (Sandbox Code Playgroud)

初始化y的第一列,其余为0.

所以编译器不会忽略内部大括号.但是,如果按顺序指定所有初始化程序且没有间隙,则不需要内括号.如果您不想指定一组完整的初始值设定项,则使用内括号可以更好地控制初始化.