为什么结构数组不需要大括号初始化?

发布于 2025-01-14 15:00:57 字数 342 浏览 3 评论 0原文

这段代码:

#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 的每个元素都应该用大括号括起来(至少我希望如此)。为什么这可能?

This code:

#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);
}

Works perfectly fine, even though each element of array ar should enclosed in braces (I would expect that at least). Why is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撩动你心 2025-01-21 15:00:57

6.7.9 Initialization/20 说明此类结构元素如何已初始化:

[..] 如果子聚合或包含的联合的初始值设定项开始
带有左大括号,该大括号及其包含的初始化程序
匹配右大括号初始化元素或成员
子聚合或包含的联合。否则,仅够
列表中的初始值设定项会考虑元素或
子聚合的成员或所包含的第一个成员
联盟;任何剩余的初始化器都会被留下来初始化下一个
当前子聚合的聚合的元素或成员
或包含的联合是一部分。

强调我的

所以它是有效的。因此

ar[] = {
    1,"asd",
    2, "qwe",
    3, "poi"
};

相当于:

 ar[] = {
    {1,"asd"},
    {2, "qwe"},
    {3, "poi"}
};

并且 ar 包含 3 个元素。

6.7.9 Initialization/20 states how such struct elements are initialized:

[..] If the initializer of a subaggregate or contained union begins
with a left brace, the initializers enclosed by that brace and its
matching right brace initialize the elements or members of the
subaggregate or the contained union. Otherwise, only enough
initializers from the list are taken to account for the elements or
members of the subaggregate or the first member of the contained
union; any remaining initializers are left to initialize the next
element or member of the aggregate of which the current subaggregate
or contained union is a part.

(emphasis mine)

So it's valid. And thus

ar[] = {
    1,"asd",
    2, "qwe",
    3, "poi"
};

is equivalent to:

 ar[] = {
    {1,"asd"},
    {2, "qwe"},
    {3, "poi"}
};

and ar contains 3 elements.

魔法少女 2025-01-21 15:00:57

这是可能的,原因很简单,标准允许这样做。

那么为什么标准允许呢?嗯,我不知道这背后是否有什么道理。最可能的原因是这仅仅是因为向后兼容性。 C语言充满了这样的东西。

然而,它被认为是不好的风格。所以要避免它。如果您在启用警告的情况下进行编译(应该),您会收到此警告:

warning: missing braces around initializer [-Wmissing-braces]
    7 | } ar[] = {
      |          ^
    8 |     1,"asd", //should be {1, "asd"},
      |     {      }
    9 |     2, "qwe", //should be {2, "qwe"},
      |     {       }
   10 |     3, "poi" //should be {3,"poi"}
      |     {
   11 | };
      | }

与许多其他语言相比,C 背后的哲学非常不同。有人可能会说,即使省略大括号是一种不好的风格,也没有真正的理由禁止省略它们。例如,它不会引起任何歧义。

It's possible for the very simple reason that the standard allows it.

So why does the standard allow it? Well, I don't know if there's any rationale behind this. The most likely reason is that it's simply because of backwards compatibility. The C language is literary full of such things.

However, it is considered bad style. So avoid it. And if you compile with warnings enabled, which you shall do, you get this warning:

warning: missing braces around initializer [-Wmissing-braces]
    7 | } ar[] = {
      |          ^
    8 |     1,"asd", //should be {1, "asd"},
      |     {      }
    9 |     2, "qwe", //should be {2, "qwe"},
      |     {       }
   10 |     3, "poi" //should be {3,"poi"}
      |     {
   11 | };
      | }

And the philosophy behind C is very different compared to many other languages. One could argue that even if it's bad style to omit the braces, there is not really a reason to forbid omitting them. For instance, it does not cause any ambiguity.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文