IEEE754 要求 NaN 是无序的;当一个或两个操作数为 NaN 时,小于、大于、等于等都应该返回 false。
F F F F F T
当在所有优化级别使用 g++ 编译时,以及使用 VC++ 的 CL.exe(32 位版本 15.00.30729.01)编译时没有优化参数或 /Od、/fp:fast 、/拱:SSE。
但是,当使用 /O1 或 /O2(以及任何/没有其他优化参数)编译时T T F F F T
,即使使用 /Op 也会产生结果。
64 位版本的 CL.exe 产生许多变体 - T T F F F T
,T T T F F T
等T T T F F F
- 取决于优化级别以及是否指定 /fp:fast,但与 32 位版本一样,似乎只有在禁用所有优化的情况下才能实现合规行为.
我犯了一些明显的错误吗?是否有某种方法可以使编译器在不牺牲所有其他优化的情况下遵守此处的标准?
#include <limits>
#include <stdio.h>
int main( int argc, char const ** argv )
{
float test = std::numeric_limits<float>::quiet_NaN();
printf( "%c %c %c %c %c %c\n",
(test < test) ? 'T' : 'F',
(test <= test) ? 'T' : 'F',
(test == test) ? 'T' : 'F',
(test > test) ? 'T' : 'F',
(test >= test) ? 'T' : 'F',
(test != test) ? 'T' : 'F'
);
return 0;
}
重现问题的示例build.cmd
:
set "PATH=c:\program files (x86)\Microsoft Visual Studio 9.0\VC\bin\amd64;c:\program files (x86)\Microsoft Visual Studio 9.0\Common7;c:\program files (x86)\Microsoft Visual Studio 9.0\Common7\IDE"
set "LIB=c:\program files (x86)\microsoft visual studio 9.0\vc\lib\x64;c:\program files\Microsoft SDKs\Windows\v6.0A\Lib\x64"
cl test.cpp /fp:fast /Od /c /I "c:\program files (x86)\microsoft visual studio 9.0\vc\include"
link "/LIBPATH:C:/Program Files (x86)/Microsoft Visual Studio 9.0/vc/lib/amd64" "/LIBPATH:C:\Program Files\Microsoft SDKs\Windows\v6.0A\/Lib/x64" /DEBUG /IGNORE:4199 /IGNORE:4221 /MACHINE:X64 /SUBSYSTEM:CONSOLE test.obj
test
编辑
作为记录,最初在使用的问题中给出的示例
inline float QNaN()
{
static int const QNaNValue = 0x7fc00000;
return *(reinterpret_cast<float const*>(&QNaNValue));
}
生成一个 NaN;正如许多评论和答案所指出的那样,这是未定义的行为,将其替换为 std::numeric_limits::quiet_NaN() 实际上解决了某些 32 位 CL.exe 版本的问题