问题描述
此代码:
#include <stdio.h>
struct
{
int i;
const char* str;
} ar[] = {
1,"asd",//should be {1,"asd"},2,"qwe",//should be {2,"qwe"},3,"poi" //should be {3,"poi"}
};
int main()
{
printf("%s\n",ar[2].str);
}
工作得很好,即使数组 ar
的每个元素都应该用大括号括起来(至少我希望如此)。为什么这是可能的?
解决方法
6.7.9 Initialization/20 说明如何初始化此类结构元素:
[..] 如果子聚合或包含联合的初始值设定项开始 带有左大括号,由该大括号括起来的初始值设定项及其 匹配右括号初始化元素或成员 子聚合或包含的联合。否则,就够了 列表中的初始值设定项被考虑到元素或 子聚合的成员或包含的第一个成员 联盟;剩下的初始化器被留下来初始化下一个 当前子聚合的聚合的元素或成员 或包含的联合是一部分。
(强调我的)
所以它是有效的。于是
ar[] = {
1,"asd",2,"qwe",3,"poi"
};
相当于:
ar[] = {
{1,"asd"},{2,"qwe"},{3,"poi"}
};
和 ar
包含 3 个元素。
这是可能的,原因很简单,标准允许这样做。
那么为什么标准允许它呢?嗯,我不知道这背后是否有任何理由。最可能的原因是这仅仅是因为向后兼容。 C语言充满了这样的东西。
然而,它被认为是不好的风格。所以避免它。如果您在启用警告的情况下编译(您应该这样做),您会收到以下警告:
warning: missing braces around initializer [-Wmissing-braces]
7 | } ar[] = {
| ^
8 | 1,//should be {1,| { }
9 | 2,//should be {2,| { }
10 | 3,"poi" //should be {3,"poi"}
| {
11 | };
| }
与许多其他语言相比,C 背后的哲学非常不同。有人可能会争辩说,即使省略大括号是一种糟糕的风格,也没有真正的理由禁止省略它们。例如,它不会引起任何歧义。