Sie vergleichen eine unsigned int
mit einer signed char
. Die Semantik dieser Art von Vergleich ist kontraintuitiv: Die meisten binären Operationen mit signed
und unsigned
Operanden werden an unsignierten Operanden ausgeführt, nachdem der vorzeichenbehaftete Wert in vorzeichenlos konvertiert wurde (wenn beide Operanden nach der Heraufstufung die gleiche Größe haben). Hier sind die Schritte:
- Der
signed char
Wert auf ein int
mit dem gleichen Wert -23
gefördert wird.
- Der Vergleich wird an
int
und unsigned int
durchgeführt. Der übliche Typ ist unsigned int
wie in der C-Norm definiert.
- Die
int
wird in eine unsigned int
mit Wert UINT_MAX - 23
umgewandelt, eine sehr große Zahl.
- Der Vergleich wird an den Werten
unsigned int
durchgeführt: 23
ist der kleinere Wert, der Vergleich wird als falsch ausgewertet.
- Der Zweig
else
wird ausgewertet, no
wird gedruckt.
Erschwerend kommt hinzu, wenn c
als long
definiert worden war, hat das Ergebnis auf abhing würde, ob long
und int
die gleiche Größe haben oder nicht. Unter Windows würde es no
drucken, während es auf 64-Bit-Linux yes
drucken würde.
Niemals signierte und vorzeichenlose Werte in Vergleichen mischen. Aktivieren Sie Compiler-Warnungen, um diese Art von Fehlern zu vermeiden (-Wall
oder -Weverything
). Sie können auch alle diese Warnungen mit -Werror
fatal machen, um diese Art von Code-Code vollständig zu vermeiden.
Eine vollständige Referenz, lesen Sie die folgenden Abschnitte der C Standard (C11) unter 6.3 Conversions:
- integer Promotions in 6.3.1.1 Boolean, Zeichen erklärt werden, und ganze Zahlen .
- Operand Konvertierungen sind in detailliert beschrieben 6.3.1.8 Übliche arithmetische Umwandlungen.
Sie können den neuesten Entwurf der C11 Norm von der Arbeitsgruppe Website herunterladen: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
Lesen Sie mehr über [Zweier-Komplement] (https://en.wikipedia.org/wiki/Two%27s_complement). und über [die impliziten Konvertierungen in C] (http: //en.cppreference.com/w/c/Sprache/Konvertierung) (insbesondere über [die arithmetischen Konvertierungen] (http://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions)). –
Die kanonische Quelle ist der [C-Standard] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) (das ist der N1570-Entwurf). Siehe 6.3.1.1 für die * integer-Promotions * (die den 'signed char'-Wert in' int' konvertieren) und 6.3.1.8 für die * üblichen arithmetischen Konvertierungen * (die beide Operanden in einen gemeinsamen Typ, unsigned int, umwandeln) , bevor der Vergleich durchgeführt wird). –