第二reinterpret_cast和严格的混叠
Second reinterpret_cast and strict aliasing
这是严格混叠冲突的典型示例:
std::uint32_t foo(float* f, std::uint32_t* i) {
*i = 1;
*f = 2;
return *i;
}
int main() {
std::uint32_t i = 3;
foo(reinterpret_cast<float*>(&i), &i);
}
但是假设我们添加第二个reinterpret_cast
:
static_assert(alignof(float) == alignof(std::uint32_t));
std::uint32_t foo(float* f, std::uint32_t* i) {
*i = 1;
*reinterpret_cast<std::uint32_t*>(f) = 2;
return *i;
}
int main() {
std::uint32_t i = 3;
std::uint32_t j = foo(reinterpret_cast<float*>(&i), &i);
assert(j == 2);
}
此代码是否正确(不调用未定义的行为(?
标准[expr.reinterpret.cast]如下:
注: 将类型为"指向
T1
的指针"的 prvalue 转换为"指向T2
的指针"类型(其中T1
和T2
是对象类型,其中T2
的对齐要求不比T1
的对齐要求严格(并转换回其原始类型,将生成原始指针值。
我们使用std::uint32_t*
类型的原始指针值来访问std::uint32_t
类型的左值。
当优化打开时,GCC 和 Clang 都会生成正确的汇编代码:
foo(float*, unsigned int*):
mov dword ptr [rsi], 1
mov dword ptr [rdi], 2
mov eax, dword ptr [rsi]
ret
以下是相应的规范性文本,expr.static_cast/13:
类型为"指向 cv1 void 的指针"的 prvalue 可以转换为类型为"指向 cv2 T 的指针"的 prvalue,其中 T 是对象类型,cv2 与 cv1 具有相同的 cv 限定条件,或比 cv1 具有更高的 cv 限定条件。如果原始指针值表示内存中某个字节的地址 A,而 A 不满足 T 的对齐要求,则未指定生成的指针值。否则,如果原始指针值指向对象 a,并且存在类型为 T(忽略 cv-限定(的对象 b,该对象可与 a 进行指针互转换,则结果是指向 b 的指针。否则,指针值在转换时保持不变。
(这段文字是相关的,因为在这种情况下,reinterpret_cast<T*>
的结果是static_cast<T *>(static_cast<void *>(...))
(
因此,如果满足对齐要求,则所有转换(uint32_t
->float
和float
->uint32_t
(都不会更改指针值。您可以访问该对象作为其类型。这里没有UB。
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- C++:"Expected '(' for function-style cast or type construction"错误
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- Shared_ptr cast vs static_cast speed
- C++20 中的严格别名规则是否允许标准 c++ unicode 字符和下划线类型之间"reinterpret
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- C++ C++ 中的函数声明,键入 CAST
- static_cast会丢弃错误,但C风格的演员cast有效
- C++ cast char * to unsigned char
- 禁用 Clang 中的"cast from pointer to smaller type uint32_t"错误
- 是否可以使用gcc 3.3版修复与int*cast相关的Sun Solaris OS 5.8分段故障
- C++ const-cast 一个引用