在ABI不向联合插入填充的平台上考虑以下代码:
union { int xi; } x; x.xi = 1;
我相信第二行显示未定义的行为,因为它违反了严格的别名规则:
引用的对象与引用的对象x.xi
是相同的对象x
.两者都是相同的存储区域,术语对象在ISO 9899:2011§3.15中定义为:
宾语
执行环境中的1个数据存储区域,其内容可以表示值
2注意引用时,对象可能被解释为具有特定类型; 见6.3.2.1.
由于一个对象只不过是一个存储区域,我得出的结论是,作为x
并x.xi
占用相同的存储,它们是同一个对象.
在有效型的x
是union { int xi; }
因为这是它已被宣布与类型.见§6.56:
6 访问其存储值的对象的有效类型是对象的声明类型(如果有).87)如果通过具有不是字符类型的类型的左值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及后续访问的有效类型修改存储的值.如果使用
memcpy
或将值复制到没有声明类型的对象中memmove
,或者将其复制为字符类型数组,则该访问的修改对象的有效类型以及不修改该值的后续访问的有效类型是有效类型复制值的对象,如果有的话.对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型.
87)分配的对象没有声明的类型.
根据6的措辞,很明显每个对象只能有一种有效类型.
在声明中,x.xi
我x
通过左键x.xi
输入来访问int
.这不是§6.57中列出的类型之一:
7对象的存储值只能由具有以下类型之一的左值表达式访问:88)
与对象的有效类型兼容的类型,
与对象的有效类型兼容的类型的限定版本,
与对象的有效类型对应的有符号或无符号类型的类型,
与有效类型的对象的限定版本对应的有符号或无符号类型的类型,
聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),或者
一个字符类型.
88)此列表的目的是指定对象可能存在或不存在别名的情况.
因此,第二行表现出不确定的行为.
由于这种解释显然是错误的,我对标准的误读在哪里?
错误是认为x
并且x.xi
是同一个对象.
union是一个对象,它包含成员对象1.它们是不同的对象,每个对象都有自己的类型.
1. (引用自:ISO/IEC 9899:20x1 6.2.5类型20)
联合类型描述了一组重叠的非成员对象,每个成员对象都有一个可选的指定名称和可能不同的类型.