cha*_*par 6 c c++ casting strict-aliasing
在ISO/IEC 9899:TC2中,标准说如下
6.3.2.3指针
- 指向对象或不完整类型的指针可以转换为指向不同对象或不完整类型的指针.如果生成的指针未针对指向类型正确对齐,则行为未定义.否则,当再次转换回来时,结果将等于原始指针.当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节.结果的连续增量(直到对象的大小)产生指向对象的剩余字节的指针.
因此,从标准中不清楚一种类型的指针可以被转换为另一种类型的指针.
Kos*_*Kos 14
严格的别名规则在其他地方定义.这是措辞:
C(ISO/IEC 9899:1999 6.5/7):
对象的存储值只能由具有以下类型之一的左值表达式访问:
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本,
- 与对象的有效类型对应的有符号或无符号类型的类型,
- 与有效类型的对象的限定版本对应的有符号或无符号类型的类型,
- 聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),或者
- 一个字符类型.
C++(ISO/IEC 14882:2011 3.10 [basicl.lval]/15):
如果程序试图通过不同于以下类型之一的左值访问对象的存储值,则行为未定义:
- 对象的动态类型,
- 一个cv限定版本的动态类型的对象,
- 与对象的动态类型类似的类型(如4.4中所定义),
- 与对象的动态类型对应的有符号或无符号类型的类型,
- 一种类型,是有符号或无符号类型,对应于对象动态类型的cv限定版本,
- 聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(递归地,包括子聚合或包含联合的元素或非静态数据成员),
- 一个类型,它是对象动态类型的(可能是cv限定的)基类类型,
- a
char
或unsigned char
类型.
如果没有对齐问题,C标准不会禁止您将指针转换为不相关的类型.但是,由于严格的别名规则,您基本上无法取消引用从此类转换中获取的指针.因此,使用这种"无效"指针唯一有用的方法是将其强制转换回正确的类型(或兼容的类型).
使用reinterpret_cast(5.2.10 [expr.reinterpret.cast]/7)在C++中大致相同:
可以将对象指针显式转换为不同类型的对象指针.当prvalue
v
类型的"指针T1
"被转换为类型"指针CVT2
",结果是static_cast<cv T2*>(static_cast<cv void*>(v))
如果两个T1
和T2
是标准布局类型(3.9)和的对准要求T2
并不比那些更严格的T1
,或者如果任一类型是void
.将"指向T1
"的类型的prvalue转换为"指向"的类型T2
(其中T1
和T2
是对象类型,并且对齐要求T2
不比那些更严格T1
)并返回其原始类型,产生原始指针值.未指定任何其他此类指针转换的结果.