int a; ...; (a == a) scheitert?

7

Wenn wir float und double auf NaN setzen, sind sie nichts mit selbst .
kann so etwas für int passieren?

    
MBZ 16.10.2010, 15:20
quelle

8 Antworten

4

Obwohl es sicherlich ungewöhnlich ist, erlaubt C ++ int als NaN .

Erstens ist es möglich, dass int Informationen außer ihrem numerischen Wert speichert. §3.9.1 / 1:

  

Bei Zeichentypen sind alle Bits der Objektdarstellung an der Wertdarstellung beteiligt. Für vorzeichenlose Zeichentypen stellen alle möglichen Bitmuster der Wertdarstellung Zahlen dar. Diese Anforderungen gelten nicht für andere Typen.

Dann müssen numeric_limits<int>::has_quiet_NaN und has_signaling_NaN nicht false für einen beliebigen Typ sein. §18.2.1.2 / 34-36:

%Vor%      

34 Wahr, wenn der Typ a hat   Darstellung für eine Ruhe   (keine Signalisierung) "Keine Nummer."

     

35 Sinnvoll für alle Fließkommawerte   Typen.

     

36 Sollen für alle wahr sein   Spezialisierungen, in denen is_iec559! =   falsch.

"Sinnvoll für alle Gleitkommatypen" ist ein wenig mühsam, da es die Möglichkeit eröffnet, dass der Wert bedeutungslos sein könnte, aber das ist sicherlich eine Extrapolation.

Wenn numeric_limits<int>::has_quiet_NaN == true , dann gibt numeric_limits<int>::quiet_NaN() einen solchen Wert zurück.

Natürlich sollten Sie sich in Ihrem Code keine Gedanken darüber machen.

    
Potatoswatter 19.10.2010, 20:15
quelle
14

Alles kann passieren, wenn Sie eine nicht initialisierte Variable mit sich selbst vergleichen. Es ist schließlich undefiniertes Verhalten. Für initialisierte int-Variablen kann dies nicht passieren.

Beachten Sie, dass Namespace-Scope-, Class-Static- und Function-Static-int-Variablen, die nicht explizit initialisiert sind, den Wert 0 erhalten. Dann werden sie nicht gleich vergleichen.

Ich habe gerade mit Clang getestet:

%Vor%

Bei der Kompilierung mit -O1 wird 0 zurückgegeben, da der Optimierer annehmen darf, dass x keinen stabilen Wert hat.

GCC ist mit dem oben genannten fehlerverzeihender und gibt 1 zurück. Das folgende bringt GCC dazu, auch 0 zurückzugeben (offensichtlich ist es nicht billiger, die Verzweigung zu wählen, wenn man wählen darf):

%Vor%

Am Ende hängt das Ergebnis nicht nur von der CPU ab, die den Code ausführt, sondern auch von allem anderen in der Toolchain.

    
Johannes Schaub - litb 16.10.2010 15:25
quelle
4

Es kann nicht passieren, wenn Sie einfache initialisierte int-Variablen vergleichen.

Es kann für int-Vergleiche vorkommen, wenn Sie auf ein Hardware-Register verweisen, z. etwas wie:

%Vor%

Dies kann auch passieren, wenn Sie eine flüchtige int-Variable mit sich selbst vergleichen, die während des Vergleichs durch einen Signal-Handler geändert wird.

    
Peter G. 16.10.2010 15:29
quelle
4

Dies ist perfekt möglich, wenn Sie nicht initialisierte Variablen vergleichen.

In der Programmiersprache C ++ wird nicht garantiert, dass eine nicht initialisierte Variable einen stabilen Wert enthält. Theoretisch führt das Arbeiten mit nicht initialisierten Werten zu undefiniertem Verhalten. In der Praxis kann das mehrfache Lesen des Wertes der gleichen nicht initialisierten Variablen leicht dazu führen, dass unterschiedliche Werte gelesen werden. Der offensichtlichste praktische Grund dafür ist, dass die Variable auf einige CPU-Register optimiert wurde.

Um die begrenzte Anzahl von CPU-Registern effizient zu verwalten, arbeiten optimierende Compiler mit dem Begriff der Wertlebensdauer einer Variablen. Die Wertlebensdauer ist im Wesentlichen der Zeitraum, in dem die Variable einen bestimmten stabilen Wert enthält. Die Lebensdauer des Werts beginnt mit der Initialisierung der Variablen und endet mit der Neuinitialisierung auf einen anderen Wert (oder auf den Zeitpunkt, an dem auf ihn zum letzten Mal zugegriffen wurde). Innerhalb der Zeit von "value lifetime" muss der Wert stabil sein, so dass das CPU-Register nicht für andere Zwecke verwendet werden kann (oder es sorgfältig gespeichert und wiederhergestellt werden muss, wenn es für andere Zwecke verwendet wird).

Außerhalb der Lebensdauer des Werts muss der Wert des Registers nicht beibehalten werden, damit er für andere Zwecke frei verwendet werden kann. Aus diesem Grund kann, wenn eine Variable durch ein CPU-Register repräsentiert wird, aber nicht initialisiert wird (dh wenn ihre Lebensdauer noch nicht begonnen hat), ihr beobachteter Wert sich absolut unvorhersehbar ändern und den neuen Wert jedes Mal erzeugen, wenn die Variable gelesen wird Der Inhalt des entsprechenden CPU-Registers ändert sich aus nicht verwandten Gründen.

Dies könnte leicht dazu führen, dass a == a auf false mit nicht initialisierter a auswertet. Natürlich ist es ziemlich überraschend zu sehen, dass es bei zwei Lesevorgängen passiert, die scheinbar so nah beieinander liegen. Aber es kann immer noch passieren. Dieses Verhalten ist absolut Standard. Der Standard garantiert nicht die Stabilität einer initialisierten Variablen.

    
AnT 16.10.2010 15:46
quelle
0

NaN ist der einzige Wert für a==a return false.

Und int unterstützt keinen NaN-Wert. Also nein, du kannst diese Situation nicht mit int haben.

Noch ein Hinweis, um zu überprüfen, ob ein Wert NaN ist, sollten Sie isnan() nicht a==a verwenden.

Zum selben Thema:

Colin Hebert 16.10.2010 15:22
quelle
0

Wie wäre es mit

? %Vor%     
Adam Trhon 16.10.2010 15:33
quelle
0

Würde vielleicht von der Compiler-Optimierung abhängen; Schau dir die Demontage an. Wenn es binary 'und' it & amp; Überprüfen Sie die Flags, nachdem es fehlschlägt, wenn a Null ist.

    
slashmais 16.10.2010 15:40
quelle
0

Nein. Die Komparation für Floats ist so definiert, dass NaN im Vergleich zu einer beliebigen Zahl false zurückgibt. Wie auch immer, für Ints gibt es eine andere Formel:

%Vor%

Dies gilt für jeden möglichen Wert von a.

EDIT: in GCC, mit einem beliebigen -O-Flag, verschwindet die Vergleiche einfach zu true.

    
ruslik 16.10.2010 15:42
quelle

Tags und Links