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));
}
当然,它不会,我们也不希望它......如果匿名结构/联合像上面那样工作,就没有理由使用它们。尽管如此,该标准在这一点上似乎并不含糊。我有什么遗漏的吗?
这看起来像是一个措辞问题,它们不应该重叠。
这在缺陷报告 (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 他们的结构或联合布局。这递归地适用,如果 包含结构或联合也是匿名的。