【发布时间】:2021-02-20 19:13:41
【问题描述】:
考虑以下代码:
#include <math.h>
#include <stdio.h>
#include <string.h>
int main() {
__uint128_t n = (__uint128_t(0x00007ffff7dd6e65ULL) << 64) |
0x63696c400a2d2d21ULL;
long double d = 0;
memcpy(&d, &n, sizeof(long double));
printf("%d\n", isnan(d));
printf("%Le\n", d);
}
当使用 clang 版本 12.0.0 (clang-1200.0.32.29) 编译并在 macOS 上运行时,它会产生以下输出:
1
3.345927e+3575
为什么isnan 将此long double 报告为NaN,而printf 将其打印为3.345927e+3575?
iostreams 和 clang++ 也是如此:
std::cout << d; // prints 3.34593e+3575
具体来说,为什么不同的 C 和 C++ API 在处理这个数字(似乎是unnormal extended precision number)时会有不同的行为?
【问题讨论】:
-
long double的底层类型是什么? 80 位 x87? -
sizeof(long double) 是 16 但我认为它应该是 80 位扩展精度 FP。
-
@EricPostpischil
isnan是否是宏似乎取决于所使用的语言(至少根据 cppreference)。这个问题用 C 和 C++ 标记。对于 C,isnanis a macro,但对于 C++isnanis an overloaded function。鉴于代码中缺少 C++ 特性,或许应该去掉 C++ 标签? -
无论该行为是否发生在 C 和 C++ 中,您都不应向语言标签发送垃圾邮件,因为它会不必要地吸引其他人的注意力,并且该行为不依赖于语言。组合语言标签应保留用于询问有关语言之间差异或交互的问题。对于这个问题,C 和 C++ 标记都可以省略。
-
我不认为这就是语言标签在实践中的使用方式,即使粗略查看已标记的问题也能看出这一点。
标签: c++ c floating-point clang