一个典型的二维数组初始化是这样的:
int arr[3][5] = { {0,1,2,3,4}, {5,6,7,8,9}, {10,11,12,13,14} };
我们被教导这是初始化数组的“正确方法”。 但它真的“正确”就好像使用单个平面列表复合文字是不正确的吗? 事实证明这也是可编译的:
int arr[3][5] = { 0,1,2,3,4, 5,6,7,8,9, 10,11,12,13,14 };
(这可能与所有数组元素都放置在连续内存中这一事实有关。)
就词法而言,两种代码在 GCC 中编译并看似产生相同的结果。 前者显然在可读性方面胜出,除了在某些情况下它会使情况变得更糟。而且我不明白为什么我们不能像我刚才那样用空格分隔“维度”。 我对这对编译器究竟意味着什么特别感兴趣。 我无法让它产生只能依赖于大括号存在的警告。可以通过任何一种方式检测过量元素。如果唯一的问题出在编译器的诊断中,那么我想知道只有在存在大括号时才会触发哪些警告/错误。
您可以自由使用格式来提高人类的可读性,例如:
int a[3][5] = {
0,1,2,3,4,
5,6,7,8,9,10,
11,12,13,14,15
};
但是,对于没有任何规则来处理特殊空格的编译器来说,这并不重要。一个分隔符。
编译器需要大括号来了解你的意图:
int a[3][5] = {
{0,1,2,3,4},
{5,6,7,8,9,10},
{11,12,13,14,15}
};
知道这一点,编译器能够在出现问题时发出警告:
int a[3][5] = {
{0,1,2,3,4},
{5,6,7,8,9,10,11}, // <--- excess elements in array initializer
{12,13,14,15}
};
或正确放置初始化常量:
int a[3][5] = {
{0,1,2,3,4},
{5,6,7}, // Use default value for remaining elements
{11,12,13,14,15}
};
顺便说一句,GCC(v 11.2.0 with
-Wall -Wextra
)不会对空括号发出任何警告:
int a[3][5] = {
{0,1,2,3,4},
{}, // Use default value for entire row
{11,12,13,14,15}
};
C 语言和现代编译器为我们提供了很多帮助,但更多的是自由,包括编写混乱和难以维护的代码的自由。 “正确”的做事方式(无论是通过教学还是公司编码标准定义的)是我们作为语言用户为自己设定的规则,以使代码易于理解和健壮。如果您为自己编写代码,则可以自由定义自己的“正确”做事方式。
花括号允许编译器更准确地解释代码,以检测人为错误,或允许更短的代码。
例如:
static int arr[3][5] = { {0,1,2,3}, {5,6}, {10,11,12,13} };
是正确的,并允许编码人员利用默认值编写更短的代码。
其他例子:
static int arr[3][5] = { {0,1,2,3,4,5}, {6,7,8,9}, {10,11,12,13,14} };
编译器会检测到一个错误。因为内存中还有 15 个 int,这真的是一个错误吗?是的海事组织。 C 是一种高级语言,接近机器是的,但它不是汇编:在数组中使用多个维度不仅仅是内存大小分配。
编译器也不完美:
static int array_4[3][5] = { {0,1,2,3,4}, { }, {10,11,12,13,14} };
这里 Visual C++ 检测到一个错误,因为
{ }
为空。但 IMO 这种语法应该是可以接受的。