我偶然发现了这段代码来检查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;
}
}
这看起来很依赖,对吗?但是,我不确定endianess,因为无论是小端还是大端,浮点数和int都可能以相同的顺序存储。
另外,我想知道是否像
volatile T x = val;
return std::isnan(x);
会起作用。
过去,它与GCC 4.6一起使用。
答案 0 :(得分:1)
另外,我想知道像
std::isnan((volatile)x)
这样的东西是否有效。
isnan
按值获取其参数,因此volatile
限定符将被丢弃。换句话说,不,这不起作用。
您发布的代码依赖于特定的浮点表示(IEEE)。它还表现出未定义的行为,因为它依赖于union
hack来检索底层浮点表示。
在关于代码审查的注释中,即使我们忽略了前一段的潜在问题(这是合理的),该函数也写得很糟:为什么函数使用运行时检查而不是编译时检查和编译时错误处理?提供两个重载会更好更容易。