2016-07-10 25 views
1

Während ein Buch über programmign Tricks lesen sah, dass -0x80000000 + -0x80000000 = 0. Das ist nicht Sinn für mich so schrieb ich ein schnelles C-Programm unten zu testen und in der Tat ist die Antwort 0:Warum ist -0x80000000 + -0x80000000 == 0? Ich

#include <stdio.h> 

int main() 
{ 
    int x = -0x80000000; 
    int y = -0x80000000; 

    int z = x + y; 

    printf("Z is: %d", z); 
    return 0; 
} 

Könnte irgendjemand etwas Licht darüber werfen, warum? Ich habe etwas über einen Überlauf gesehen, aber ich kann nicht sehen, wie ein Überlauf eher 0 verursacht als eine Ausnahme oder einen anderen Fehler. Ich bekomme keine Warnung oder irgendetwas.

+1

Ja, es ist Überlauf. Nein, C warnt normalerweise nicht oder gibt Exceptions bei Integer-Überläufen aus. Sie sehen 0, weil die unteren 32 Bits der tatsächlichen Antwort alle 0 sind, und wenn ein Integer-Überlauf auftritt, erhalten Sie die Antwort modulo 4294967296, das heißt modulo 2^32. –

Antwort

2

Was hier passiert, ist vorzeichenbehafteter Integer-Überlauf, der undefined behavior ist, weil die genaue Darstellung von Ganzzahlen mit Vorzeichen nicht definiert ist.

In der Praxis jedoch verwenden die meisten Computer die Zweierkomplement-Darstellung für Ganzzahlen mit Vorzeichen, und dieses spezielle Programm nutzt das aus.

0x80000000 ist eine vorzeichenlose Integer-Konstante. Die negiert es und ändert den Ausdruck in signed. Angenommen, int ist 32-Bit auf Ihrem System, dieser Wert passt immer noch. Tatsächlich ist es der kleinste Wert, den ein vorzeichenbehafteter 32-Bit int halten kann, und die hexadezimale Darstellung dieser Zahl ist zufällig 0x80000000.

Wenn Sie Zahlen in der Zweierkomplementdarstellung hinzufügen, müssen Sie sich keine Gedanken über das Zeichen machen. Sie werden genau wie vorzeichenlose Nummern hinzugefügt. So

wenn wir x und y fügen wir diese:

0x80000000 
+ 0x80000000 
------------- 
    0x100000000 

Da ein int auf Ihrem System 32-Bit ist nur die untersten 32 Bits gehalten werden. Und der Wert dieser Bits ist 0.

Beachten Sie, dass dies tatsächlich undefiniert Verhalten ist. Es funktioniert, weil Ihr Computer 2-Komplement-Darstellung für Ganzzahlen mit Vorzeichen verwendet und int 32-Bit ist. Dies ist für die meisten Maschinen/Compiler üblich, aber nicht für alle.

+1

Der Typ von '0x80000000' ist Implementierung definiert. Es kann unterschrieben werden. – 2501

+2

Das einfache Negieren eines vorzeichenlosen Typs ergibt keinen signierten Typ. Unter einigen Annahmen wird im Fall von OP der Wert ohne Vorzeichen auf den (positiven) Wert 0x80000000 zurückgesetzt. – 2501

+0

danke, half mir zu verstehen, was vor sich geht. – MHartley

1

Was Sie sehen, ist eine Menge von Implementierung definiert Verhalten, sehr wahrscheinlich Auslösen undefiniertes Verhalten zur Laufzeit. Mehr als das ist nicht möglich, ohne Details über Ihre und Buchautoren Architektur zu wissen.

Das Ergebnis ist ohne zusätzliche Informationen nicht aussagekräftig. Wenn Sie eine definitive Antwort benötigen, konsultieren Sie die Typbereiche für Ihre Architektur und stellen Sie sicher, dass die Ergebnisse der Zuweisungen und Arithmetik in ihre jeweiligen Typen passen.