本机isnan检查C ++

时间:2014-04-07 09:03:11

标签: c++

我偶然发现了这段代码来检查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一起使用。

1 个答案:

答案 0 :(得分:1)

  

另外,我想知道像std::isnan((volatile)x)这样的东西是否有效。

isnan按值获取其参数,因此volatile限定符将被丢弃。换句话说,不,这不起作用。

您发布的代码依赖于特定的浮点表示(IEEE)。它还表现出未定义的行为,因为它依赖于union hack来检索底层浮点表示。

在关于代码审查的注释中,即使我们忽略了前一段的潜在问题(这是合理的),该函数也写得很糟:为什么函数使用运行时检查而不是编译时检查和编译时错误处理?提供两个重载会更好更容易。