2010-10-10 7 views
7
main() { 
    if (-1 < (unsigned char) 1) 
    printf("less than"); 
    else   
    printf("NOT less than"); 
} 

Drucke less than. Weil (unsigned char) 1in(signed char) 1 konvertiert wird und dann: (signed) -1 < (signed) 1, so ist Ausgabe less than.Dateityppromotions während arithmetischer Operationen: -1 <(unsinged int) 1 == falsch

Aber wenn ich den obigen Code-if ((-1 < (unsigned int) 1)

ändern, dann ist der Ausgang NOT less than.

Es ist so offensichtlich, dass, wenn ich unsigned char unsigned int ändern:

  • (signiert) -1 in unsigned int umgewandelt wird [genau gegenüber geschieht]
  • da -1 gespeichert als 2 Kompliment von 1; das Bitmuster wird als 255 (wahrscheinlich)
  • ausgewertet, also wird 255 < 1 zu false ausgewertet und wird sonst ausgeführt.
  • auch wenn Sie int a = -1; anstelle von ‚-1‘ gleiches Ergebnis

Fragen ersetzen:

  1. während und ohne Vorzeichen Arithmetik ... wie sicher sein, wenn umgewandelt wird unterzeichnet unsigniert oder umgekehrt.

  2. warum ist die Umwandlung verschiedener für die Arithmetik zwischen unsigned char und char: anscheinend nicht signiert und ohne Vorzeichen int umgewandelt und int: anscheinend unterzeichnet ist Konverter unsigned

PS: Ich weiß, dass dies nicht Compiler abhängig..so sage nicht, dass es ist.

+0

sind nicht alle Literale Standard Int? (unsigned char -> int promotion gegen int -> unsigned int promotion) – flownt

Antwort

10

Die Regeln sind wie folgt:

6.3.1.8 Übliche arithmetische Umwandlungen

...

Ansonsten werden die Integer-Aktionen auf beiden Operanden durchgeführt. Dann werden die folgenden Regeln zu den geförderten Operanden angewandt:

  1. Wenn beiden Operanden vom gleichen Typ sind, dann keine weitere Umsetzung benötigt wird.
  2. Wenn beide Operanden vorzeichenbehaftete Integer-Typen haben oder beide vorzeichenlose Integertypen haben, wird der Operand mit dem Typ des Integer-Konvertierungsrangs in den Typ des Operanden mit größerem Rang konvertiert.
  3. Andernfalls, wenn der Operand mit dem vorzeichenlosen Integer-Typ einen Rang größer oder gleich dem Rang des Typs des anderen Operanden hat, wird der Operand mit vorzeichenbehafteten Integer-Typ in den Typ des Operanden mit vorzeichenlosen Integer-Typ konvertiert.
  4. Wenn der Typ des Operanden mit vorzeichenbehafteten Integer-Typ alle Werte vom Typ des Operanden mit vorzeichenlosen Integer-Typen darstellen kann, wird der Operand mit Ganzzahl ohne Vorzeichen in den Typ des Operanden mit Ganzzahl mit Vorzeichen konvertiert Art.
  5. Andernfalls werden beide Operanden in den vorzeichenlosen Integertyp umgewandelt, der dem Typ des Operanden mit Ganzzahl mit Vorzeichen entspricht.

Die Regeln arbeiten dann wie folgt:

  • -1 < (unsigned char) 1

Zuerst beide Operanden werden zu Ints umgewandelt (weil ein int alle Werte von unsigned char darstellen kann). Dann wird der Vergleich an diesen signierten Typen vorgenommen. Regel 1 wird dann verwendet. Der Vergleich ist erfolgreich.

  • -1 < (unsigned int) 1

Ein int nicht alle Werte von unsigned int darstellen einem SO3 Regel verwendet wird und die vorzeichenbehaftete ganze Zahl ist mit einem unsigned integer (UINT_MAX - 1) umgewandelt. Der Vergleich schlägt fehl.

+1

"rank"? Was bedeutet das? – bakra

+0

@bakra: Sie können es sich als eine "Bestellung" der Typen vorstellen. Ein langer int hat beispielsweise einen höheren Rang als ein char. Siehe 6.3.1.1 für die offizielle Definition des Rangs. –

+1

@bakra: "Rang" eines Integraltyps ist an anderer Stelle im C-Standard definiert, aber der Kern davon ist, welcher Typ einen größeren Bereich möglicher Werte plus ein paar Ausnahmen hat. Insbesondere "Der Rang eines vorzeichenbehafteten Integer-Typs muss größer als der Rang irgendeines Ganzzahl-Typs mit Vorzeichen mit geringerer Genauigkeit sein." und "Der Rang eines vorzeichenlosen ganzzahligen Typs muss dem Rang des entsprechenden vorzeichenbehafteten ganzzahligen Typs entsprechen, falls vorhanden." – aschepler

1

Dies ist aufgrund Integer-Promotions. Beide Argumente können als int dargestellt werden, so dass sie in einen int konvertiert werden.

ISO C 6.3.1.1 Absatz 2:

Wenn ein int alle Werte des ursprünglichen Typs darstellen kann, wird der Wert in einen int umgewandelt wird; Andernfalls wird es in einen unsigned int konvertiert. Diese werden als Integer promotions.48) bezeichnet. Alle anderen Typen werden durch die Integer-Promotions nicht geändert.