【问题标题】:Is this a C11 anonymous struct?这是 C11 匿名结构吗?
【发布时间】:2023-03-04 15:39:01
【问题描述】:

我正在研究 C11 草案,它说

没有标签的结构类型的未命名成员称为匿名结构;没有标签的联合类型的未命名成员称为匿名联合。匿名结构或联合的成员被视为包含结构或联合的成员。

所以我构建了以下测试用例

// struct type with no tag
typedef struct {
  unsigned char a;
  unsigned char b;
  // ... Some other members ...
  unsigned char w;
} AToW;

union
{
  AToW; // <- unnamed member
  unsigned char bytes[sizeof(AToW)];
} myUnion;

Clang 和 GCC 都抱怨未命名的成员,说声明没有效果。是我做错了什么,还是他们根本不支持该功能?

【问题讨论】:

  • 我不认为这就是匿名结构。注意“标签”这个词。那是结构或联合的 type 标记,如struct foo { ... } f; - 这里“foo”是标记。
  • @user3477950 是的,AToW 没有标签。
  • 值得注意的是,Clang 和 GCC 似乎都允许您将 AToW 用作扩展,以与 Plan9 和 Microsoft 兼容。 gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html#Unnamed-Fields

标签: c struct c11 anonymous-struct


【解决方案1】:

不,那不是无名成员。

一个例子是:

struct outer {
    int a;
    struct {
        int b;
        int c;
    };
    int d;
};

包含成员bc 的内部结构是struct outer未命名成员。此未命名成员的成员 bc 被视为包含结构的成员。

这对于包含联合而不是包含结构可能更有用。特别是,它可用于定义类似于 Pascal 或 Ada 变体记录的内容:

enum variant_type { t_int, t_double, t_pointer, t_pair };
struct variant {
    enum variant_type type;
    union {
        int i;
        double d;
        void *p;
        struct {
            int x;
            int y;
        };
    };
};

这使您可以将idp 直接作为struct variant 对象的成员引用,而不是为变体部分创建假名。如果某些变体需要多个成员,您可以在匿名联合中嵌套匿名结构。

(它与 Pascal 和 Ada 的不同之处在于,在给定 type 成员的值的情况下,没有强制执行哪个变体处于活动状态的机制;这对你来说是 C。)

在您的示例中,AToW 是您之前定义的结构类型的 typedef。你不被允许裸露的

AToW;

在结构定义的中间,你不能有一个光秃秃的

int;

C11 添加了在另一个结构中定义嵌套匿名结构的功能,但只能通过在该点定义新的匿名结构类型。您不能拥有先前定义的类型的匿名结构成员。语言可以被定义为允许它,并且语义(我认为)相当简单——但定义两种不同的方式来做同样的事情并没有多大意义。 (对于上面的“结构”,请阅读“结构或联合”。)

引用N1570 draft(非常接近发布的 2011 ISO C 标准),第 6.7.2.1 节第 13 段:

类型说明符是结构说明符的未命名成员 没有标签被称为匿名结构;一个未命名的成员,其类型 说明符是一个没有标签的联合说明符被称为 anonymous 联合。匿名结构或联合的成员被考虑 成为包含结构或联合的成员。这适用 如果包含结构或联合也是匿名的,则递归。

结构说明符包含关键字struct,后跟一个可选标识符(标记,在这种情况下省略),然后是包含在{和@987654339中的一系列声明@。在您的情况下,AToW 是类型名称,而不是结构说明符,因此它不能用于定义匿名结构

【讨论】:

  • 我看不出这与我的情况有什么不同,除了您使用结构说明符作为类型,而我使用普通标识符作为类型。为什么我的AToW; 不是无名会员?如果我将其更改为AToW x;,它将成为命名成员。
  • @JohannesSchaub-litb:请参阅我回答的更新后的最后一段。 (TL;DR:因为标准是这样说的。)
  • "你不能有一个裸 AToW;在结构定义的中间,你不能有一个裸 int;" - 引用我给不准吗?它说“没有标签的结构类型的未命名成员称为匿名结构;没有标签的联合类型的未命名成员称为匿名联合”并继续定义其语义。所以问题归结为“为什么是 AToW;不是匿名结构?”我还没有看到。 “整数;”不是,因为“int”不是结构类型,这很容易。
  • “您不能拥有先前定义类型的匿名结构成员。”,我会对说明这一点的规范引用非常感兴趣。那确实会回答我的问题。
  • 谢谢,似乎较新的草稿解决了这个问题。整个混乱来自与一位朋友的谈话,他告诉我struct A { struct B; }; 将包含一个匿名结构。那将与 C++ 不兼容,所以我想看看,发现有人可能使用typedef。但似乎我使用的草稿太旧了。
猜你喜欢
  • 2018-03-28
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 2012-09-11
  • 2012-02-14
  • 2012-01-27
  • 2015-02-23
  • 2017-02-02
相关资源
最近更新 更多