C11 中的匿名结构和联合是否被错误描述?

问题描述 投票:0回答:1

C 标准,关于匿名结构和联合:

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

注意强调:匿名结构/联合的成员不是在包含结构/联合的范围中,而是完全是它的成员。但这是有责任的:

6.7.2.1 p16. 联合的大小足以容纳其最大的成员。任何时候最多可以将一个成员的值存储在联合对象中。指向联合对象的指针,经过适当转换后,指向其每个成员(或者如果成员是位字段,则指向它所在的单元),反之亦然。

总而言之,这些似乎意味着(命名)联合内匿名结构的成员的行为就像联合中位于同一位置、互斥的成员。所以以下应该有效:

union Foo
{
    struct
    {
        char a;
        char b;
    };
};

int main(void) {
    union Foo f;
    assert(&f == &(f.a) && &f == &(f.b));
}

当然,它不会,我们也不希望它......如果匿名结构/联合像上面那样工作,就没有理由使用它们。尽管如此,该标准在这一点上似乎并不含糊。我有什么遗漏的吗?

c language-lawyer c11
1个回答
11
投票

TL;博士

这看起来像是一个措辞问题,它们不应该重叠。

详情

这在缺陷报告 (DR) 499 中有所涉及,其中询问:

给出以下代码:

union U {   
  struct {
    char B1;
    char B2;
    char B3;
    char B4;  
  };  
  int word; 
} u;

B1、B2、B3、B4 的存储是否重叠?

根据 6.7.2.1#13,成员在存储时应重叠,因为它们 成为‘Union U’的成员。
至少有一个实现(GCC)似乎 不要认为它们是重叠的。
至少一种实现 (IBM的XL LE AIX)认为它们作为标准是重叠的 目前状态。

委员会的回应是:

存储不重叠。

相关问题可在 DR 502 中找到,并且两者都可以通过协调措辞更改来解决。

和(强调)

将 §6.7.2.1 p13 更改为:

没有标记的结构体类型的未命名成员称为匿名结构体;没有标签的联合类型的未命名成员是 称为匿名工会。匿名结构的成员或 union 被认为是包含结构的成员或 联盟。如果包含结构或联合,则这递归地适用 也是匿名的。

至:

没有标记的结构体类型的未命名成员称为匿名结构体;没有标签的联合类型的未命名成员是 称为匿名工会。匿名者的姓名成员 结构或联合被添加到包含的名称空间 结构或联合。这递归地适用,如果包含 结构或联合也是匿名的。

将充分解决问题。

更新:经过额外的委员会讨论后,最终选择的措辞是(强调):

没有标签的结构类型的未命名成员称为匿名成员 结构;没有标签的联合类型的未命名成员称为 匿名联盟。匿名结构或联合的成员是 被认为是包含结构或联合的成员,keeping 他们的结构或联合布局。这递归地适用,如果 包含结构或联合也是匿名的。

© www.soinside.com 2019 - 2024. All rights reserved.