为啥在 gcc 和 clang 上通过优化将大 double 转换为 uint16_t 会给出不同的答案
Posted
技术标签:
【中文标题】为啥在 gcc 和 clang 上通过优化将大 double 转换为 uint16_t 会给出不同的答案【英文标题】:Why does converting an large double to a uint16_t with optimizations on gcc and clang give different answers为什么在 gcc 和 clang 上通过优化将大 double 转换为 uint16_t 会给出不同的答案 【发布时间】:2018-12-01 11:49:04 【问题描述】:开启优化后,下面的代码会在 gcc 上产生不同的结果。如果没有优化,gcc 会产生与 clang 相同的结果。
#include <cfloat>
#include <cstdint>
double big_dbl() return DBL_MAX;
int main()
return static_cast<std::uint16_t>(big_dbl());
-O0
的汇编器输出显示 gcc 和 clang 都调用 empty_dbl
并使用 cvttsd2si
进行浮点转换->int 转换,然后转换为 16 位无符号值并生成 0
.将优化级别提高到 -01
可以优化两个编译器中的 empty_dbl
调用,但 clang 仍然给出 0
作为强制转换的结果,而 gcc 给出 65535。可以使用 compiler explorer 看到结果。
这是 gcc 优化器中的错误还是未定义的行为,因此优化器可以做它喜欢的事情?
这最近困扰着我们,从某种意义上说,谢天谢地,因为它显示了 big_dbl
使用不正确的情况,我们已经正确修复了代码,但我想了解与 gcc 的区别。
【问题讨论】:
相关:***.com/questions/526070/… 【参考方案1】:Quote 来自当前标准草案:
浮点类型的纯右值可以转换为整数类型的纯右值。转换截断;也就是说,小数部分被丢弃。 如果截断的值不能在目标类型中表示,则行为未定义。
所以实现可以为您的情况做任何他们喜欢的事情,因为行为是未定义的。
【讨论】:
以上是关于为啥在 gcc 和 clang 上通过优化将大 double 转换为 uint16_t 会给出不同的答案的主要内容,如果未能解决你的问题,请参考以下文章