我偶然发现这段代码来检查 NaN:
/**
* isnan(val) returns true if val is nan.
* We cannot rely on std::isnan or x!=x, because GCC may wrongly optimize it
* away when compiling with -ffast-math (default in RASR).
* This function basically does 3 things:
* - ignore the sign (first bit is dropped with <<1)
* - interpret val as an unsigned integer (union)
* - compares val to the nan-bitmask (ones in the exponent, non-zero significand)
**/
template<typename T>
inline bool isnan(T val) {
if (sizeof(val) == 4) {
union { f32 f; u32 x; } u = { (f32)val };
return (u.x << 1) > 0xff000000u;
} else if (sizeof(val) == 8) {
union { f64 f; u64 x; } u = { (f64)val };
return (u.x << 1) > 0x7ff0000000000000u;
} else {
std::cerr << "isnan is not implemented for sizeof(datatype)=="
<< sizeof(val) << std::endl;
}
}
这看起来依赖于架构,对吧?但是,我不确定字节序,因为无论是小字节序还是大字节序,float 和 int 可能以相同的顺序存储。
另外,我想知道是不是像
volatile T x = val;
return std::isnan(x);
本来可以的。
这在过去与 GCC 4.6 一起使用。
最佳答案
Also, I wonder whether something like
std::isnan((volatile)x)
would have worked.
isnan
按值获取其参数,因此 volatile
限定符将被丢弃。换句话说,不,这行不通。
您发布的代码依赖于特定的浮点表示法 (IEEE)。它还表现出未定义的行为,因为它依赖于 union
hack 来检索底层的 float 表示。
关于代码审查的注释,即使我们忽略上一段的潜在问题(这是有道理的),该函数还是写得很糟糕:为什么该函数使用运行时检查而不是编译时检查和编译时错误处理?如果只提供两个重载会更好更容易。
关于c++ - C++ 中的 native isnan 检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22907923/