Nach IEEE754 müssen NaNs ungeordnet sein; kleiner als, größer als, gleich usw. sollten alle falsch zurückgeben, wenn einer oder beide Operanden NaN sind.
Das folgende Beispiel liefert das korrekte F F F F F T
wie erwartet, wenn es mit g ++ auf allen Optimierungsebenen kompiliert wird und mit CL ++.exe (32-Bit Version 15.00.30729.01) von VC ++ ohne Optimierungsargumente oder eine Kombination aus / Od kompiliert wird , / fp: schnell, / arch: SSE.
Wenn jedoch mit / O1 oder / O2 (und / oder anderen Optimierungsargumenten) kompiliert wird, ergibt sich T T F F F T
, auch wenn / Op ebenfalls angegeben ist.
Die 64-Bit-Version von CL.exe bietet viele Variationen - T T F F F T
, T T T F F T
, T T T F F F
usw. - abhängig von der Optimierungsstufe und ob / fp: fast angegeben ist, aber wie bei der 32-Bit-Version , konformes Verhalten scheint nur bei deaktivierter Optimierung möglich zu sein.
Mache ich einen offensichtlichen Fehler? Gibt es eine Möglichkeit, den Compiler dazu zu veranlassen, die Standards zu erfüllen, ohne dabei alle anderen Optimierungen zu opfern?
%Vor% Ein Beispiel build.cmd
, das das Problem reproduziert:
BEARBEITEN
Für das Protokoll wurde das ursprünglich in der Frage angegebene Beispiel verwendet
%Vor%um ein NaN zu erzeugen; Wie eine Reihe von Kommentaren und Antworten darauf hinweist, ist dies ein undefiniertes Verhalten, und das Ersetzen durch std :: numeric_limits :: quiet_NaN () hat das Problem für einige Versionen der 32-Bit-CL.exe
behobenZusammenfassend gab es eine Reihe von separaten Problemen:
Der ursprüngliche Beispielcode ergab ein undefiniertes Verhalten, indem er striktes Aliasing verletzte. Dies zu beheben war ausreichend, um das Problem für einige Versionen des 32-Bit-Compilers zu lösen.
mit diesem Problem behoben, entfernt /fp:fast
das Problem für alle Versionen der 32-Bit-und 64-Bit-Compiler für mich verfügbar
Martinho erwähnt, dass das Problem in cl 16.0 nicht mehr existiert, auch nicht mit /fp:fast
Sie rufen undefiniertes Verhalten auf, indem Sie int*
auf float*
umwandeln. Ich habe Ihren Code mit VS 2010 ausprobiert, wobei std::numeric_limits<float>::quiet_NaN()
anstelle der Besetzung verwendet wurde, und es gab das erwartete Ergebnis (alle außer der letzten waren false
) mit /O2
und /fp:fast
.
AKTUALISIEREN
Ich habe das überarbeitete Beispiel in VS 2010 und VS 2005 kopiert. In beiden Fällen liefert der 32-Bit-Compiler korrekte Ergebnisse ( F F F F F T
), während der 64-Bit-Compiler keine Ergebnisse liefert.
Tags und Links c++ visual-studio-2008 visual-c++ ieee-754