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