【发布时间】:2020-02-08 07:34:25
【问题描述】:
严格的别名规则说
如果程序尝试通过以下方式访问对象的存储值 行为是以下类型之一以外的泛左值 未定义:
——对象的动态类型,
——对象动态类型的 cv 限定版本,
——与对象的动态类型类似(如 4.4 中定义)的类型,
——对象的动态类型对应的有符号或无符号类型,
— 有符号或无符号类型,对应于对象动态类型的 cv 限定版本,
——一种聚合或联合类型,在其元素或非静态数据成员中包含上述类型之一(递归地,包括子聚合或包含联合的元素或非静态数据成员)
我想知道以下程序是否已经包含未定义的行为以及是否存在“对存储值的访问”:
#include <cstdint>
void foo() {
std::int32_t i = 1;
float f = 1.0f;
std::int32_t& r = reinterpret_cast<std::int32_t&>(f);
std::int32_t* p = reinterpret_cast<std::int32_t*>(&f);
}
据我所见,float 指针对 int 引用的转换等价于 `*reinterpret_cast(&x):
如果“指向 T1 的指针”类型的表达式可以显式表示,则可以将 T1 类型的泛左值表达式强制转换为“对 T2 的引用”类型 使用 reinterpret_cast 转换为“指向 T2 的指针”类型 result 引用与源 glvalue 相同的对象,但使用 指定类型。 [注意:也就是说,对于左值,引用转换 reinterpret_cast(x) 和转换的效果一样 *reinterpret_cast(&x) 带有内置的 & 和 * 运算符(同样适用于 reinterpret_cast(x))。 ——尾注]
对于指针,reinterpret_cast 归结为转换为 void*,然后转换为目标类型:
对象指针可以显式转换为不同类型的对象指针。72 当对象指针类型的纯右值 v 为 转换为对象指针类型“pointer to cv T”,结果为 static_cast(static_cast(v))。
两个静态转换的语义定义为:
“指向 cv1 void 的指针”类型的纯右值可以转换为“指向 cv2 T 的指针”类型的纯右值,其中 T 是对象类型,而 cv2 与 cv 限定相同或大于 cv 限定, 简历1。空指针值转换为空指针值 目的地类型。如果原始指针值代表 内存中一个字节的地址A和A满足对齐 T 的要求,那么得到的指针值代表相同 地址作为原始指针值,即A。任意的结果 其他此类指针转换未指定。
由于int32_t 和float 具有相同的大小和对齐方式,我应该得到一个指向相同地址的新指针。我想知道的是如果
引用转换 reinterpret_cast(x) 与 使用内置的 & 和 * 运算符转换 *reinterpret_cast(&x)
已经构成对存储值的访问,或者如果以后必须在某个地方进行访问以违反严格的别名规则。
【问题讨论】:
-
我建议添加语言律师,这样不懂问题的人就不会投反对票
标签: c++ language-lawyer undefined-behavior reinterpret-cast strict-aliasing