Omitting Sizes while Initializing C/C++ Multidimensional Arrays(初始化 C/C++ 多维数组时省略大小)
问题描述
我对 C/C++ 编译器的了解是它们在初始化多维数组时会忽略内括号.
所以,你不能这样做:
int myArray[][] = { { 2, 3 }, { 4, 5 }, { 4, 1 } };
因为编译器会看到它完全一样
int myArray[][] = { 2, 3, 4, 5, 4, 1 };
现在它不知道它是 6 * 1, 3 * 2, 2 * 3, 1 * 6, 还是别的什么(因为这可以是一个部分初始化列表,不一定是完整的).
>我的问题是,为什么这在许多编译器中都有效?
int myArray[][2] = { { 2 }, { 4, 5 }, { 4, 1 } };
编译器直观地"将其视为:
int myArray[][2] = { { 2, 0 }, { 4, 5 }, { 4, 1 } };
这意味着它不会忽略大括号.到目前为止,我已经在三种不同的编译器上尝试过它,并且一切正常.
我希望答案是这只是依赖于编译器".我无权访问标准,因此请提供来自标准的答案.我不需要直觉,我有我的.
以下内容来自《The C Programming Language》A8.7节作者:K&R,第 2 版,第 219,220 页:
<块引用>聚合是结构或数组.如果聚合包含聚合类型的成员,初始化规则递归应用.可以在初始化中省略大括号,如下所示:如果聚合成员的初始值设定项,该成员本身就是聚合以左大括号开头,然后是后续的逗号分隔列表初始化器初始化子聚合的成员;它是初始化器比成员多是错误的.如果,然而,子聚合的初始值设定项不以左开头大括号,然后只考虑列表中的足够元素子聚合的成员;剩下的成员留给初始化子聚合的聚合的下一个成员是一部分.例如,
<块引用>
int x[] = { 1, 3, 5 };
声明并初始化 x 为具有三个成员的一维数组,因为没有指定大小和
<块引用>共有三个初始化器.
因此,鉴于这一行
int myArray[][2] = { { 2 }, { 4, 5 }, { 4, 1 } };
编译器会递归地初始化数组,注意每个子数组都以左大括号开头,初始化器的个数不超过要求的个数,并且会统计子数组的个数来确定数组的第一维.
以下来自The C Programming Language"的A8.7节作者:K&R,第 2 版,第 220 页:
<块引用>float y[4][3] = {{ 1, 3, 5 },{ 2, 4, 6 },{ 3, 5, 7 }};
<块引用>
是一个全括号初始化:1
、3
和5
初始化数组的第一行y[0]
,即y[0][0]
、y[0][1]
、y[0][2]
>.同样,接下来的两行初始化 y[1]
和 y[2]
.初始化器提前结束,因此 y[3]
的元素被初始化为 0
.
<块引用>
float y[4][3] = {1, 3, 5, 2, 4, 6, 3, 5, 7};
注意这两种情况都会初始化数组的第四行零,因为没有指定足够的初始值设定项.
float y[4][3] = {{ 1 }, { 2 }, { 3 }, { 4 }};
初始化y
的第一列,剩下的0
.
所以编译器不会忽略内部大括号.但是,如果您按顺序无间隙地指定所有初始值设定项,则内大括号是可选的.如果您不想指定一整套初始化程序,则使用内大括号可以让您更好地控制初始化.
What I know about C/C++ compilers is that they ignore inner braces while initializing multidimensional arrays.
So, you can't do this:
int myArray[][] = { { 2, 3 }, { 4, 5 }, { 4, 1 } };
because the compiler will see it exactly as
int myArray[][] = { 2, 3, 4, 5, 4, 1 };
and now it doesn't know if it is 6 * 1, 3 * 2, 2 * 3, 1 * 6, or even something else (since this can be a partial initialization list, not necessarily complete).
My question is, why does this work in many compilers?
int myArray[][2] = { { 2 }, { 4, 5 }, { 4, 1 } };
The compiler "intuitively" sees it as:
int myArray[][2] = { { 2, 0 }, { 4, 5 }, { 4, 1 } };
which means it doesn't ignore the braces. I've tried it on three different compilers till now and all worked.
I expect the answer to be "this is just compiler-dependent". I don't have access to the standard, so please provide an answer from the standard. I don't need gut feelings, I have mine.
The following is from section A8.7 of "The C Programming Language" by K&R, 2nd edition, pages 219,220:
An aggregate is a structure or array. If an aggregate contains members of aggregate type, the initialization rules apply recursively. Braces may be elided in the initialization as follows: if the initializer for an aggregate's member that is itself an aggregate begins with a left brace, then the succeeding comma-separated list of initializers initialize the members of the sub aggregate; it is erroneous for there to be more initializers than members. If, however, the initializer for a subaggregate does not begin with a left brace, then only enough elements from the list are taken to account of the members of the subaggregate; any remaining members are left to initialize the next member of the aggregate of which the subaggregate is a part. For example,
int x[] = { 1, 3, 5 };
declares and initializes x as a 1-dimensional array with three members, since no size was specified and
there are three initializers.
Therefore, given this line
int myArray[][2] = { { 2 }, { 4, 5 }, { 4, 1 } };
the compiler will recursively initialize the array, noting that each subarray starts with a left brace and has no more than the required number of initializers, and will count the number of subarrays to determine the first dimension of the array.
The following is from section A8.7 of "The C Programming Language" by K&R, 2nd edition, page 220:
float y[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 } };
is a completely-bracketed initialization:
1
,3
and5
initialize the first row of the arrayy[0]
, namelyy[0][0]
,y[0][1]
, andy[0][2]
. Likewise the next two lines initializey[1]
andy[2]
. The initializer ends early, and therefore the elements ofy[3]
are initialized with0
. Precisely the same effect could have been achieved by
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
.
So the compiler doesn't ignore the inner braces. However, the inner braces are optional if you specify all of the initializers in order with no gaps. Using the inner braces gives you more control over the initialization, if you don't want to specify a full set of initializers.
这篇关于初始化 C/C++ 多维数组时省略大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:初始化 C/C++ 多维数组时省略大小
基础教程推荐
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 从 std::cin 读取密码 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01