9

IEEE754 では、NaN が順序付けされていない必要があります。一方または両方のオペランドが NaN の場合、より小さい、より大きい、等しいなどはすべて false を返す必要があります。

以下のサンプルはF F F F F T、すべての最適化レベルで g++ を使用してコンパイルした場合、および最適化引数を指定せずに、または /Od、/fp:fast、 /arch:SSE.

ただし、/O1 または /O2 (およびその他の最適化引数を使用する/使用しない) を使用してコンパイルすると、T T F F F T/Op も指定した場合でも結果が得られます。

CL.exe の 64 ビット バージョンは、最適化レベルと /fp:fast が指定されているかどうかに応じて、多くのバリエーション( 、T T F F F Tなど)を生成しますが、32 ビット バージョンと同様に、準拠した動作はすべての最適化が無効になっている場合にのみ可能であるようです。 .T T T F F TT T T F F F

私は明らかな間違いを犯していますか?他のすべての最適化を犠牲にすることなく、ここでコンパイラを標準に準拠させる方法はありますか?

#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 の一部のバージョンの問題が修正されました。

4

4 に答える 4

4

int*にキャストすることにより、未定義の動作を呼び出していますfloat*。キャストの代わりに使用して、VS 2010 でコードを試してみましstd::numeric_limits<float>::quiet_NaN()たが、期待どおりの結果が得られました (最後のものを除くすべてfalse)/O2/fp:fast.

アップデート

修正した例を VS 2010 と VS 2005 の両方にコピー アンド ペーストしました。これらの両方で、32 ビット コンパイラは正しい結果 ( F F F F F T) を生成しますが、64 ビット コンパイラは生成しません。

于 2013-04-03T12:03:47.160 に答える
4

これは、QNaN 関数が厳密なエイリアシングに違反して UB を呼び出すためです。VS コンパイラは、あらゆる動作を生成する権利を十分に有しています。

于 2013-04-03T12:03:57.367 に答える