C++ 第二次重新解释_强制转换和严格别名
这是一种严格的别名冲突:C++ 第二次重新解释_强制转换和严格别名,c++,language-lawyer,reinterpret-cast,strict-aliasing,C++,Language Lawyer,Reinterpret Cast,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); } 此代码正确吗(不调用未定义的行为) 标准[expr.reinterpret.cast]: 注:将“
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);
}
此代码正确吗(不调用未定义的行为)
标准[expr.reinterpret.cast]:
注:将“指针指向T1
”类型的PR值转换为“指针指向T2
”类型(其中T1
和T2
是对象类型,其中T2
的对齐要求不比T1
的对齐要求更严格)并返回到其原始类型会产生原始指针值
我们使用类型为std::uint32\u t*
的原始指针值访问类型为std::uint32\u t
的左值
启用优化时,GCC和Clang都会生成正确的汇编代码:
foo(float*, unsigned int*):
mov dword ptr [rsi], 1
mov dword ptr [rdi], 2
mov eax, dword ptr [rsi]
ret
以下是相应的规范性文本: 类型为“指向cv1 void的指针”的prvalue可转换为类型为“指向cv2 T的指针”的prvalue,其中T为对象类型,cv2与cv1相同或大于cv1。如果原始指针值表示内存中字节的地址A,而A不满足T的对齐要求,则结果指针值未指定。否则,如果原始指针值指向对象a,并且存在类型为T(忽略cv限定)的对象b可与a进行指针互换,则结果是指向b的指针。否则,指针值将通过转换保持不变 (本文涉及,因为在这种情况下,
reinterpret\u cast
的结果是static\u cast(static\u cast(…)
)
因此,如果满足对齐要求,则所有转换(既不是
uint32_t
->float
也不是float
->uint32_t
)都不会更改指针值。您可以将对象作为其类型进行访问。这里没有UB。哦,该死的。我没有读所有的代码。这实际上没有问题,因为f
实际上指向了uint32\t
。评论撤回。
foo(float*, unsigned int*):
mov dword ptr [rsi], 1
mov dword ptr [rdi], 2
mov eax, dword ptr [rsi]
ret