示例代码:
struct S { int x; };
int func()
{
S s{2};
return (int &)s; // Equivalent to *reinterpret_cast<int *>(&s)
}
我认为这很常见,被认为是可以接受的 . 该标准确保结构中没有初始填充 . 但是,这种情况未在严格别名规则(C17 [basic.lval] / 11)中列出:
如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:(11.1)对象的动态类型,(11.2)动态的cv限定版本对象的类型,(11.3)与对象的动态类型相似的类型(如7.5中所定义),(11.4)对应于对象的动态类型的有符号或无符号类型,(11.5)a type是有符号或无符号类型,对应于对象动态类型的cv限定版本,(11.6)聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(包括,递归地,子聚合或包含联合的元素或非静态数据成员,(11.7)一种类型,它是对象动态类型的(可能是cv限定的)基类类型,(11.8)一个char,unsigned char或std :: byte类型 .
很明显,对象 s
正在访问其存储值 .
项目符号点中列出的类型是 the type of the glvalue doing the access ,而不是被访问对象的类型 . 在这段代码中,glvalue类型是 int
,它不是聚合类型或联合类型,排除了11.6 .
我的问题是:这个代码是否正确,如果是,那么允许上述哪一个要点?
2 回答
演员的行为归结为[expr.static.cast] / 13;
指针可互换的定义是:
所以在原始代码中,
s
和s.x
是指针可互换的,因此(int &)s
实际上指定了s.x
.因此,在严格别名规则中,正在访问其存储值的对象是
s.x
而不是s
,因此没有问题,代码是正确的 .我认为这是expr.reinterpret.cast#11
[1]当结果引用与源glvalue相同的对象时,这有时被称为类型双关语
支持@ M.M关于指针不可挽回的答案:
来自cppreference:
与