C11中的匿名结构和联合被错误地描述了吗?

时间:2018-04-04 17:30:51

标签: c language-lawyer c11

关于匿名结构和联盟的C标准:

  

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

注意强调:而不是匿名struct / union的成员在包含struct / union的范围中,而是完全成员。但是还有责任:

  

6.7.2.1 p16.联合的大小足以包含其中最大的成员。最多一个成员的值可以随时存储在union对象中。指向联合对象的指针(适当转换)指向其每个成员(或者如果成员是位字段,则指向它所在的单位),反之亦然。

总而言之,这些似乎意味着(命名)联盟中的匿名结构的成员表现得像联合的共同位置,相互排斥的成员。所以以下内容应该有效:

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

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

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

1 个答案:

答案 0 :(得分:8)

TL; DR

这看起来像是措辞上的问题,它们不应重叠。

详细信息

Defect Report (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,成员在存储时应重叠,因为它们   成为“联盟U”的成员。
   似乎至少有一个实现(GCC)   不要认为它们是重叠的。
   至少一种实施   (IBM的XL LE AIX)将它们作为标准重叠   当前状态。

委员会的回应是:

  

存储空间不重叠。

     

DR 502中将发现一个相关的问题,并且可以通过协调措辞来解决这两个问题。

  

将§6.7.2.1p13更改自:

     
    

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

  
     

收件人:

     
    

没有标签的结构类型的未命名成员称为匿名结构;没有标签的union类型的未命名成员是     称为匿名联合。匿名成员的姓名     结构或联合添加到包含的名称空间     结构或联合。如果包含     结构或联合也是匿名的。

  
     

将足以解决问题。