【问题标题】:Why must a struct member always have an identifier?为什么结构成员必须始终具有标识符?
【发布时间】:2021-12-20 05:33:52
【问题描述】:

为什么结构成员必须始终有一个标识符?答案当然是因为语言是这样定义的,但我想了解其背后的原因。

typedef union {
    int a;
    struct {
        int a; //Why is an identifier necessary here?
        int b;
    } s;
} u;

【问题讨论】:

标签: c struct union


【解决方案1】:

这里有语法问题。考虑int a, b, c;。这声明了三个对象。 int a, b; 声明两个,int a; 声明一个。那么int; 应该声明多少?当没有声明符的声明出现在其他上下文中时,它不声明任何对象。例如,struct foo { int x; }; 定义了 struct foo 类型,但它没有声明该类型的对象。

我们可以对结构中的声明做一个例外,并说,如果它们没有声明符,那么它们声明一个未命名的成员。但随后我们在语法中引入了另一种特殊情况。然后struct foo { int x; };,它没有声明符,当它出现在结构定义中时,它会声明一个struct foo类型的成员对象,但当它出现在结构定义之外时,它不会声明任何对象。

所以这增加了语言的复杂性。而且没有必要;想要一个结构中的成员的人总是可以给它一个名字,并且可以选择一个不会干扰其他代码的名字。

【讨论】:

    【解决方案2】:

    //这里为什么需要标识符?

    这个a 与结构外的a 不同。编译器需要知道你想访问哪一个

    如果您使用不同的名称,您可以在 union 中使用匿名结构

    typedef union {
        int a;
        struct {
            int b;
            int c;
        };
    } u;
    
    u foo(int x, int y, int z)
    {
       u un;
       u.a = x;
       u.b = y;
       u.c = z;
    }
    

    【讨论】:

      【解决方案3】:

      其实位域成员是不需要名字的,至少根据gcc -std=c99 -Wall -Wextra -pedantic,编译这段代码的时候不会给出警告:

      struct Foo
      {
        char x;
        unsigned :8;
      };
      

      如果您真的不想为不是位字段的成员提供标识符,您可以将其命名为 _reserved0 之类的名称,以明确表明这只是您不想要的保留空间从您的代码访问。

      我不知道编写 C 标准的人的意见。也许他们认为没有名称的结构成员几乎总是一个错误(即程序员忘记了名称),他们想帮助人们捕捉这些错误,但他们对规则做了一些例外。

      【讨论】:

      • Per footnote 126 of the (draft) C11 standard:“未命名的位域结构成员可用于填充以符合外部强加的布局。”
      • 也可以使用 cmets 来表示保留了一些空间。我一直讨厌像“_reserved”这样的标签。如果所有类型的结构成员都可以是匿名的,我认为该标准会很好。我猜唯一真正的缺点是这里的问题增加了。
      猜你喜欢
      • 2011-07-13
      • 2016-05-18
      • 1970-01-01
      • 2014-12-08
      • 2020-04-12
      • 2012-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多