Visual Studio 2022 如何处理双倍到长整型超范围转换?

How does Visual Studio 2022 handle double-to-long long out-of-range conversion?

提问人:yeputons 提问时间:10/14/2023 最后编辑:yeputons 更新时间:10/14/2023 访问量:89

问:

请考虑以下使用 Visual Studio 2022 编译的 C++ 代码:

#include <iostream>
#include <intrin.h>
int main() {
    std::cout << _cvt_dtoll_sent(1e31) << "\n";
    std::cout << _cvt_dtoll_sat(1e31) << "\n";
    std::cout << _cvt_dtoll_fast(1e31) << "\n";
    std::cout << (long long)1e31 << "\n";
}

在 x86 中,它打印:

-9223372036854775808
9223372036854775807
4016683251292700672
-4571153621781053440

在 x64 中,它打印:

-9223372036854775808
9223372036854775807
-9223372036854775808
-4571153621781053440

该程序使用四种不同的方式转换为 .由于不适合(有符号的 64 位整数),因此行为在 C++ 标准下未定义。但是,VS2022 有一个默认为 /fpcvt:BC 的特殊选项,引用:doublelong long1e31long long

/fpcvt:BC 选项还使到有符号类型的转换在源无效时返回最小可能值

因此,我希望返回哨兵值 ,就像 一样。但是,它不仅不会返回哨兵,而且与转换的“饱和”或“快速”版本不一致。为什么?(long long)1e31-9223372036854775808_cvt_dtoll_sent

C++ 可视化工作室 浮点 visual-studio-2022

评论

0赞 Eljay 10/14/2023
你有没有试过明确提供?超出范围,因此实际上具有未定义的行为(无效的转换可能会生成不同的值或异常),或者实现定义的不可靠行为(如果您愿意)。/fpcvt:BC_cvt_dtoll_fast
0赞 yeputons 10/14/2023
@Eljay我做到了,没有任何区别:非内在演员仍然做一些完全不同的事情。
0赞 Adrian Mole 10/14/2023
我会想象“cast”版本在编译时被“解析”(因为想要一个更好的词);其他三个强制使用内部函数,这些函数响应平台和标志。
0赞 Adrian Mole 10/14/2023
...yes:警告 C4056:浮点常数算术溢出
0赞 Eljay 10/14/2023
有趣的是,我的行为与我自己的小函数不同。编译时未定义行为运行时未定义行为。(好吧,表面上实现定义了行为,作为扩展。除非你发现了一个真正的编译器错误和/或文档错误!(long long)1e31to_long_long(1e31)auto to_long_long(double x) -> long long { return static_cast<long long>(x); }

答: 暂无答案