此问题基于this
请考虑以下内容:
struct Hdr { int type; };
struct A { Hdr h; };
union Big {
Hdr h;
A a;
};
并假设对于Big big
,我们知道big.a
是联合的活跃成员。是big.h.type
的访问权限未定义的行为?
我认为确实是UB,基于:
... [注:为了简化并集的使用,做出了一项特殊保证:如果一个标准布局的并集包含几个共享一个公共初始序列([class.mem])的标准布局的结构,并且如果此标准布局联合类型的对象的非静态数据成员处于活动状态并且是标准布局结构之一,则允许检查任何标准布局结构成员的公共初始序列;参见[class.mem]。 —尾注]
我们有一个标准布局联合,它具有标准布局成员结构,但据了解,即使{{1的第一个数据成员)Hdr
和A
的{{3}}为空}}的类型为A
。
我正确的是,这是UB吗?如果不是,那么我会误解了哪个共同的初始序列点,从而定义了访问Hdr
?
答案 0 :(得分:4)
我认为您的解释没有错。
根据您的报价,只有在A
和Hdr
共享包含Hdr::type
的公共初始序列的情况下,此定义才明确。
引用定义公共初始序列的规则:
[class.mem]两种标准布局结构([class.prop])类型的公共初始序列是非静态数据成员和位字段的最长序列(按声明顺序),从第一个此类实体开始在每个结构中,以便相应的实体具有与布局兼容的类型...
因此,A
和Hdr
的前两个成员(即int
和Hdr
)是与布局兼容的类型,如果它们是公用的。在
[basic.types]如果T1和T2是相同类型(它们不是同一类型),则两个类型cv1 T1和cv2 T2是布局兼容类型,布局兼容枚举(它们不是枚举),或与布局兼容的标准布局类类型(其中只有一个是类类型)。
由于不适用,int
和Hdr
不兼容布局,因此A
和Hdr
的公共初始序列为空,因此没有成员引用的特殊保证适用于此。
您可以使用包装器来规避规则的微妙之处:
union Big {
struct {
Hdr h;
} w;
A a;
} big;
在这里,即使big.w.h.type
处于活动状态,对访问big.a
的定义也很好。附言匿名结构在这里可以使包装器不可见。不幸的是,这些不是标准的C ++格式。