-2147483648 ist die kleinste Ganzzahl für den Ganzzahltyp mit 32 Bit, aber es scheint, dass sie im if(...)
Satz überläuft :
if (-2147483648 > 0)
std::cout << "true";
else
std::cout << "false";
Dies wird true
in meinen Tests gedruckt . Wenn wir jedoch -2147483648 in eine Ganzzahl umwandeln, ist das Ergebnis anders:
if (int(-2147483648) > 0)
std::cout << "true";
else
std::cout << "false";
Dies wird gedruckt false
.
Ich bin verwirrt. Kann jemand eine Erklärung dazu geben?
Update 02-05-2012:
Vielen Dank für Ihre Kommentare. In meinem Compiler beträgt die Größe von int 4 Byte. Ich benutze VC für einige einfache Tests. Ich habe die Beschreibung in meiner Frage geändert.
Das sind viele sehr gute Antworten in diesem Beitrag. AndreyT hat sehr ausführlich erklärt, wie sich der Compiler bei solchen Eingaben verhält und wie diese minimale Ganzzahl implementiert wurde. qPCR4vir gab andererseits einige verwandte "Kuriositäten" an und wie Ganzzahlen dargestellt werden. Sehr beeindruckend!
quelle
INT_MIN
von haben-9223372036854775808
, wenn sieCHAR_BIT
16 ist. Und selbst mitCHAR_BIT == 8
undsizeof(int
== 4) `erhalten Sie möglicherweise,-9223372036854775807
weil C keine 2-Komplement-Zahlen benötigt.Antworten:
-2147483648
ist keine "Zahl". Die C ++ - Sprache unterstützt keine negativen Literalwerte.-2147483648
ist eigentlich ein Ausdruck: ein positiver Literalwert2147483648
mit einem unären-
Operator davor. Der Wert2147483648
ist anscheinend zu groß für die positive Seite desint
Bereichs auf Ihrer Plattform. Wenn der Typlong int
auf Ihrer Plattform eine größere Reichweite hätte, müsste der Compiler automatisch davon ausgehen, dass2147483648
derlong int
Typ vorhanden ist. (In C ++ 11 müsste der Compiler auch denlong long int
Typ berücksichtigen .) Dies würde den Compiler veranlassen,-2147483648
in der Domäne eines größeren Typs auszuwerten, und das Ergebnis wäre erwartungsgemäß negativ.In Ihrem Fall entspricht der Bereich anscheinend
long int
jedoch dem Bereich vonint
, und im Allgemeinen gibt es keinen ganzzahligen Typ mit einer größeren Reichweite alsint
auf Ihrer Plattform. Dies bedeutet formal, dass die positive Konstante2147483648
alle verfügbaren vorzeichenbehafteten Ganzzahltypen überläuft, was wiederum bedeutet, dass das Verhalten Ihres Programms undefiniert ist. (Es ist ein bisschen seltsam, dass sich die Sprachspezifikation in solchen Fällen für undefiniertes Verhalten entscheidet, anstatt eine Diagnosemeldung zu benötigen, aber so ist es.)In der Praxis kann unter Berücksichtigung der Tatsache, dass das Verhalten nicht definiert ist, dies
2147483648
als ein implementierungsabhängiger negativer Wert interpretiert werden, der zufällig positiv wird, nachdem er unär-
angewendet wurde. Alternativ könnten einige Implementierungen versuchen, vorzeichenlose Typen zur Darstellung des Werts zu verwenden (z. B. mussten Compiler in C89 / 90 verwendet werdenunsigned long int
, jedoch nicht in C99 oder C ++). Implementierungen dürfen alles tun, da das Verhalten ohnehin undefiniert ist.Als Randnotiz ist dies der Grund, warum Konstanten wie
INT_MIN
typischerweise definiert werden alsanstelle der scheinbar einfacheren
Letzteres würde nicht wie beabsichtigt funktionieren.
quelle
#define INT_MIN (-2147483647 - 1)
.int
. Die Implementierung von OP hat möglicherweise keinen 64-Bit-Typ.-1.0
wird als negativer Doppelwert analysiert, nicht wahr?unsigned long int
In diesem Zusammenhang ist nur der erste Standard C (C89 / 90) zulässig , in C99 wurde diese Berechtigung jedoch entfernt. Nicht angehängte Literale in C und C ++ müssen signierte Typen haben. Wenn Sie hier einen nicht signierten Typ sehen, wenn ein signierter funktionieren würde, bedeutet dies, dass Ihr Compiler defekt ist. Wenn Sie hier einen vorzeichenlosen Typ sehen, bei dem kein vorzeichenbehafteter Typ funktionieren würde, ist dies nur eine spezifische Manifestation undefinierten Verhaltens.Der Compiler (VC2012) befördert auf die "minimalen" Ganzzahlen, die die Werte enthalten können. Im ersten Fall kann
signed int
(undlong int
) nicht (bevor das Zeichen angewendet wird), aberunsigned int
kann:2147483648
hatunsigned int
???? Art. In der Sekunde zwingst duint
aus demunsigned
.Hier sind verwandte "Kuriositäten":
C ++ 11 Standard :
…
…
Und dies sind die Beförderungsregeln für Ganzzahlen im Standard.
quelle
int
,long int
,unsigned long int
unsuffixed Dezimalkonstanten darzustellen. Dies war die einzige Sprache, in der vorzeichenlose Typen für nicht angehängte Dezimalkonstanten verwendet werden konnten. In C ++ 98 war esint
oderlong int
. Keine vorzeichenlosen Typen erlaubt. Weder C (ab C99) noch C ++ erlauben dem Compiler, in diesem Zusammenhang vorzeichenlose Typen zu verwenden. Es steht Ihrem Compiler natürlich frei, nicht signierte Typen zu verwenden, wenn keiner der signierten funktioniert, aber dies ist immer noch nur eine spezifische Manifestation von undefiniertem Verhalten.int
oderlong int
darstellen muss2147483648
. Auch AFAIK, in VC2012 beideint
undlong int
sind 32-Bit-Typen. Dies bedeutet, dass das Literal in VC20122147483648
zu undefiniertem Verhalten führen sollte . Wenn das Verhalten undefiniert ist, darf der Compiler alles tun. Das würde bedeuten, dass VC2012 nicht kaputt ist. Es wurde lediglich eine irreführende Diagnosemeldung ausgegeben. Anstatt Ihnen zu sagen, dass das Verhalten völlig undefiniert ist, hat es sich entschieden, einen vorzeichenlosen Typ zu verwenden.long
, und keine Diagnose ausstellen müssen? Das scheint kaputt zu sein.Kurz
2147483648
gesagt-2147483648
,(-(-2147483648) > 0)
läuft über und isttrue
.Dies ist , wie
2147483648
sieht binär mögen.Außerdem ist bei vorzeichenbehafteten Binärberechnungen das höchstwertige Bit ("MSB") das Vorzeichenbit. Diese Frage kann erklären, warum.
quelle
Da negation ( )
-2147483648
tatsächlich darauf angewendet wird, entspricht die Zahl nicht Ihren Erwartungen. Es ist eigentlich das Äquivalent dieses Pseudocodes:2147483648
-
operator -(2147483648)
Angenommen, Ihr Compiler ist
sizeof(int)
gleich4
undCHAR_BIT
definiert als8
, würde der2147483648
Überlauf den maximal vorzeichenbehafteten Wert einer Ganzzahl (2147483647
) ergeben. Was ist also das Maximum plus eins? Lassen Sie uns das mit einer 4-Bit-, 2s-Kompliment-Ganzzahl klären.Warten! 8 läuft über die ganze Zahl! Was machen wir? Verwenden Sie die vorzeichenlose Darstellung
1000
der Bits und interpretieren Sie sie als vorzeichenbehaftete Ganzzahl. Diese Darstellung lässt uns-8
die 2s-Komplement-Negation anwenden8
, die, wie wir alle wissen, größer ist als0
.Aus diesem Grund wird
<limits.h>
(und<climits>
) üblicherweiseINT_MIN
als((-2147483647) - 1)
- definiert, sodass die maximal vorzeichenbehaftete Ganzzahl (0x7FFFFFFF
) negiert (0x80000001
) und dann dekrementiert (0x80000000
) wird.quelle
-8
immer noch-8
.-(8)
was in C ++ dasselbe ist wie-8
- es ist eine Negation, die auf ein Literal angewendet wird, nicht auf ein negatives Literal. Das Literal ist8
, das nicht in eine vorzeichenbehaftete 4-Bit-Ganzzahl passt, daher muss es ohne Vorzeichen sein. Das Muster ist1000
. Bisher ist Ihre Antwort richtig. Die Komplement-Negation der beiden1000
in 4 Bit ist1000
, es spielt keine Rolle, ob sie signiert oder nicht signiert ist. Ihre Antwort lautet "Interpretieren Sie die Bits als vorzeichenbehaftete Ganzzahl", wodurch der Wert-8
nach der Komplement-Negation der beiden genau wie vor der Negation erstellt wird.8
. Negation wird angewendet (Modulo 16), was zu einer endgültigen Antwort von führt8
. Die Codierung ist immer noch 1000, aber der Wert ist unterschiedlich, da ein vorzeichenloser Typ ausgewählt wurde.