C中的多维数组初始化

我正在阅读Kochen的书“C编程”,我很困惑他解释了多维数组的初始化

这里

特别是,我不明白以下句子的含义请注意,在这种情况下,需要内部大括号来强制正确初始化。 没有它们,第三行的前两行和前两个元素将被初始化。 我不确定这句话意味着什么。

使用内括号,数组看起来像这样:

10 5 -3 0 0 9 0 0 0 0 32 20 1 0 0 0 0 8 0 0 

所以在每一行中最后2个值都为零(因为你没有为它们设置一个值。没有内括号,数组看起来像这样:

 10 5 -3 9 0 0 32 20 1 0 0 8 0 0 0 0 0 0 0 0 

只有前12个元素才会成为给定值,其余元素将为0。

这是因为M[4][5]数组有20个元素(4行,5列),如果没有使用内部大括号明确指定行,则初始化的默认顺序是逐行的。

这意味着如果您将相同的12个值分配为简单的线性列表,而没有内部的大括号,则将值分配给前两行(2 * 5 = 10个元素)加上第三个行的前两个列行。 (未明确初始化的数组的其余8个元素将自动设置为0。)

C编译器知道每行只有5列,并且每次达到5列边距时,会自动将数字列表包装到下一行。 从而,

 int M[4][5] = {10, 5, -3, 9, 0, 0, 32, 20, 1, 0, 0, 8}; 

被理解为是指

 int M[4][5] = { {10, 5, -3, 9, 0}, { 0, 32, 20, 1, 0}, { 0, 8, 0, 0, 0}, { 0, 0, 0, 0, 0} }; 

您可以通过使用内部大括号将12个值分隔为您自己喜欢的行来覆盖默认顺序(但对于此数组M定义,每行自然不超过5列)。

例如,当您使用内部大括号将相同的12个值分隔为四个3个集合(如书中所示的页面)时 ,那些内部大括号将被解释为初始化多维数组的单独行。 结果将初始化数组的四行 ,但只有这四行的前三列,将其余列设置为零(每行末尾两个空白零值)。

也就是说,C编译器知道数组M在每一行中有5列,因此它会将缺少的列添加到每一行,这样每行有5列,因此数组总共有20列值:

 int M[4][5] = { {10, 5, -3}, { 9, 0, 0}, {32, 20, 1}, { 0, 0, 8} }; 

被理解为是指

 int M[4][5] = { {10, 5, -3, 0, 0}, { 9, 0, 0, 0, 0}, {32, 20, 1, 0, 0}, { 0, 0, 8, 0, 0} }; 

由于所有数组内部都表现为1d数组,因此您必须使用括号指定您初始化的行。

举个例子:

 int a[4][5] = { { 1, 2, 3 }, // those are the elements of the first row. // only the first 3 elements are initialized { 1, 2, 3, 4} // those are the elements of the 2nd row. // only the first 4 element are initialized }; // everything else will be equal to 0 

 int a[4][5] = { 1, 2, 3, 1, 2, 3, 4}; // this will initialize first 5 elements // of the first row and then continue // with the 2nd one making the first 2 // elements to be 3 and 4 respectivly // everything else will be equal to 0 

这将有助于看到具体的例子。

多维数组是一个数组数组。 (对于长的一维数组而言,这不仅仅是语法糖。)

在初始化程序中,省略两个尾随元素(隐式初始化为零)和内部花括号是合法的。

鉴于:

 int arr[2][2]; 

完整初始化可能如下所示:

 int arr[2][2] = { { 10, 20 }, { 30, 40 } }; 

你可以(但恕我直言)不要省略内括号:

 int arr[2][2] = { 10, 20, 30, 40 }; 

并且编译器将初始化器的元素映射到arr的元素。

如果省略尾随元素:

 int arr[2][2] = { { 10, 20 } }; 

然后第二行被隐式初始化为{ 0, 0 }

或者你可以写:

 int arr[2][2] = { { 10 }, { 20 } }; 

这会将值10和20分配给每行的第一个元素,而不是第一行。

同样,如果没有看到一个例子,很难确切地说出作者正在谈论的是什么,但是内部括号告诉编译器开始一个新行,即使第一行不完整。

如果为所有4个元素(或更常见的是所有X * Y元素)提供初始化器,则内部支撑不是严格必需的; 无论哪种方式,元素的顺序都是相同的。

就个人而言,无论如何,我发现包括所有内括号更清楚,因为它们反映了您正在初始化的实际结构。

(那么除了语法糖之外,1维数组和2维数组之间有什么区别呢?鉴于上面的arr声明,如果它与1维数组相同,那么arr[0][2]会与arr[1][0] ,第二个索引溢出到第二行。并且它可能在实践中以这种方式工作,但实际上arr[0][2]具有未定义的行为。这确实具有实际后果;优化编译器可以假设所有边界都在范围内,并且如果违反该假设,则生成行为不当的代码。)

另见这个问题 。

C中的多维数组只是一维数组的“语法糖”。 当你分配一个4 x 5的int数组时,你真的在​​内存中为一行中的20个整数分配空间。 这些整数存储为第一行的所有元素,然后存储第二行的所有元素,等等。

如果没有内括号,初始化程序也是1D,并表示您要初始化这20个整数中的前12个,即前两行和第三行的前两个元素。