【问题标题】:Casting a negative const double to unsigned results in 0 while non-const double is fine将负 const double 转换为 unsigned 结果为 0 而 non-const double 很好
【发布时间】:2021-04-30 15:10:22
【问题描述】:

我有这个代码:

#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;
}

当我运行它时,这是输出:

-400
4294966896
-400
0

为什么会这样?适度的谷歌搜索在这件事上没有显示任何内容。

【问题讨论】:

  • 啊哈!思考了大约 10 分钟后,我意识到不同之处不在于第二个值是 const,而是(意外地)它也是 constexpr。所以第二个强制转换是在编译时计算的,第一个是在运行时计算的。
  • @MooingDuck 这实际上是一个很好的答案,从“UB,鼻恶魔”中得到很好的刷新
  • 更好的标题可能是“将负值转换为 unsigned 会导致奇怪的行为”
  • @SergeyA:这不是答案,因为正确答案是“UB,鼻恶魔”。解释的行为只是一个有趣的旁注。
  • 我想,“不是答案”也将是高度特定于编译器和优化级别的。这是一个很好的理论来解释为什么会发生这种情况(对于这个特定的编译器和优化级别的组合)。

标签: c++ constants static-cast


【解决方案1】:

来自cppreference.com

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

-400 不适合unsigned,因此行为未定义。试图推理任何类型的一致性都是无用的。

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

【讨论】:

  • 任何东西?它会射你吗,天哪;)
  • @anastaciu 是的。
  • 如果我是赌徒,我不会赌它会射你。但如果它要向你开枪,它至少是符合标准的。
  • 只是不要在 gcc 中打开-Woptimize-out-non-pedantic-programmers 标志,你会没事的。
  • 如果未定义的行为导致编译器开枪,请向编译器供应商提交错误报告。这种行为可能会对编译器供应商的声誉产生不利影响,尽管他们的最佳意图是使用达尔文自选算法减少未定义的行为
猜你喜欢
  • 2015-10-15
  • 1970-01-01
  • 1970-01-01
  • 2014-09-12
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多