C++ 将负常量双精度强制转换为无符号将导致0,而非常量双精度则可以

C++ 将负常量双精度强制转换为无符号将导致0,而非常量双精度则可以,c++,constants,static-cast,C++,Constants,Static Cast,我有以下代码: #include <iostream> int main() { double val = -400.0; const double constVal = -400.0; std::cout << val << std::endl; std::cout << static_cast<unsigned>(val) << std::endl; std::cout <

我有以下代码:

#include <iostream>

int main() {
    double val = -400.0;
    const double constVal = -400.0;
    std::cout << val << std::endl;
    std::cout << static_cast<unsigned>(val) << std::endl;
    std::cout << constVal << std::endl;
    std::cout << static_cast<unsigned>(constVal) << std::endl;

    return 0;
}
为什么会发生这种情况?适度的谷歌搜索在这件事上没有任何表现。

来源:

浮点类型的prvalue可以转换为任意类型的prvalue 整数类型。小数部分被截断,即 小数部分被丢弃。如果该值不能放入 目标类型,行为未定义(即使目标 类型为无符号,模运算不适用)。如果 目标类型为bool,这是一种布尔转换(见下文)

-400不能放入未签名的
中,因此行为未定义。试图对任何类型的一致性进行推理都是徒劳的


由于这是未定义的行为,编译器在这种情况下可以做任何它想做的事情。通常情况下,他们会做任何让他们(定义的)行为的其余部分更容易编码的事情。尽管如此,编译器不太可能让恶魔从你的鼻子里飞出来,但你不应该期望有任何特别的行为。

有什么吗?它能射死你吗,耶稣;)@是的,如果我是一个赌徒,我不会赌它会杀了你。但是,如果它向你开枪,它至少会符合标准。只要不要在gcc中打开
-woOptimize out non-pedantic programmers
标志,你就会没事的。啊哈!在思考了大约10分钟后,我意识到区别不在于第二个值是
const
,而是它也是(偶然的)
constepr
。因此,第二次强制转换是在编译时计算的,第一次是在运行时计算的。@MooingDuck这实际上是一个很好的答案,“UB,鼻腔恶魔”的一个很好的刷新。更好的标题可能是“将负值强制转换为未签名的
会导致奇怪的行为”@SergeyA:这不是一个答案,因为正确的答案是“UB,鼻腔恶魔”。解释的行为只是一个有趣的旁注。“不是答案”也将是高度特定于编译器和优化级别的,我想。这是一个很好的理论解释为什么会发生这种情况(对于这种特定的编译器和优化级别组合)。
-400
4294966896
-400
0