最标准的方式是直接调用 std::isnan,但仅限浮点类型(float、double、long double),需包含头文件;传入整数如 std::isnan(0) 会编译失败。

怎么用 std::isnan 判断 NaN?
直接调用 std::isnan 是最标准的方式,但它只接受浮点类型(float、double、long double),不接受整数或指针。传入整数会编译失败,比如 std::isnan(0) 报错 —— 因为没有匹配的重载。
使用前必须包含头文件:(C++11 起)。
示例:
#include#include int main() { double x = 0.0 / 0.0; // 产生 NaN std::cout << std::isnan(x) << "\n"; // 输出 1 }
为什么 val != val 也能判断 NaN?
IEEE 754 规定:NaN 不等于任何值,包括它自己。所以 x != x 成立当且仅当 x 是 NaN(前提是 x 是浮点类型,且未开启 -ffast-math 等破坏 IEEE 语义的编译选项)。
立即学习“C++免费学习笔记(深入)”;
这个技巧无需函数调用、无头文件依赖,适合极简场景或模板元编程中规避 std::isnan 的 SFINAE 问题。
但要注意:
-
val != val在启用-ffast-math(GCC/Clang)时可能被优化掉,结果恒为false - 对
std::complex或自定义浮点类不适用 - 可读性差,团队协作中建议加注释说明意图
常见误用:传入整数、未检查类型、忽略域错误
std::isnan 不是类型安全的“万能检测”——它不会自动转换整数。以下写法都错:
-
std::isnan(5)→ 编译失败:找不到匹配函数 -
std::isnan(static_cast→ 强转后丢失 NaN 信息,永远返回(x)) false -
std::isnan(some_ptr)→ 类型不匹配,编译报错
另外,某些老平台(如部分嵌入式 libc)可能不实现 std::isnan,此时需回退到 val != val 或宏 isnan()(来自 ,注意命名空间)。
跨平台兼容性与替代方案
Windows MSVC 默认支持 std::isnan(C++11+),但早期 MinGW 可能需要定义 _USE_MATH_DEFINES 并包含 ;Android NDK r21+ 没问题,r19 及更早需确认 STL 版本。
若需最大兼容性,可封装一层:
#includetemplate constexpr bool is_nan(T x) noexcept { if constexpr (std::is_floating_point_v ) { return std::isnan(x); } else { return false; } }
这样既能阻止整数误用,又避免宏污染和头文件冲突。
真正容易被忽略的是:NaN 有符号位和 payload,std::isnan 只管“是不是 NaN”,不管它是 quiet 还是 signaling,也不反映 payload 内容 —— 如果业务需要区分,得用 std::fpclassify 或位操作解析二进制表示。








