2016-07-17 14 views
6

Ich bin auf diese Frage gestoßen.Warum ist die Ausgabe dieses C-Codes "Nein"?

#include <stdio.h> 

int main(void) { 
    // your code goes here 
    unsigned int i = 23; 
    signed char c = -23; 

    if (i > c) 
     printf("yes"); 
    else 
     printf("no"); 

    return 0; 
} 

vermag ich nicht zu verstehen, warum die Ausgabe dieses Codes no ist.

Kann mir jemand helfen zu verstehen, wie der Vergleichsoperator funktioniert, wenn ein Vergleich zwischen int und char in C durchgeführt wird?

+4

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)). –

+0

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). –

Antwort

11

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

+0

Nützliche Referenz als Ergänzung zu dieser Antwort: https://www.securecoding.cert.org/confluence/display/c/INT02-C.+Understand+integer+conversion+Rules – chrphb

+0

Und 6.3.1.1 für die * Integer-Promotions *. [Hier ist ein Link] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) zum N1570-Entwurf des C11-Standards. –