2010-12-03 2 views
8

Warum warnt GCC nur für die Situationen 1 und 3 und nicht 2 im folgenden Code?GCC warnt nicht bei Verwendung von == op mit einer signierten Variablen und einem unsignierten Literal

Ich kompiliere mit -Wall und -g Flags.

int main() { 

    unsigned int ui = 4; 
    int si = 6; 

    if (si == ui) { // Warning comparison b/w signed and unsigned 
     printf("xxxx"); 
    } 

    if (si == 2U) { // No Warning --- WHY ??? 
     printf("xxxx"); 
    } 

    if (si > 2U) { // Warning comparison b/w signed and unsigned 
     printf("xxxx"); 
    } 

    return 0; 
} 

Antwort

4

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html:

-Wconversion Abschnitt:

für explizite Casts warnen Sie nicht wie abs ((int) x) und ui = (unsigned) -1, oder wenn der Wert nicht durch die Umwandlung wie in abs (2.0) geändert.

Da 2U wörtliche ist, gcc, dass:

  • wenn si < 0, dann (unsigned) si >= 2^31 daher s1 != 2U.
  • Wenn si > 0, dann (unsigned) si hat den gleichen Wert wie si, also (unsigned) si == 2U wenn und nur wenn si == 2.

Abschließend die signierten si mit literal 2U Vergleich ist die gleiche wie si mit 2 Vergleich, das heißt, würde das Ergebnis nicht durch si == 2Usi zu unsigned Umwandlung geändert werden.

Wenn Sie vergleichen mit 2^32-1 (4294967295U), die größten in 32-Bit unsigned int, die in int nicht darstellbaren, dann si sogar, um es gleich sein könnte, wenn si selbst negativ ist, kann dies nicht was Sie wollten, so wird eine Warnung mit -Wextra Option generiert.

1

Möglicherweise weil es keine Mehrdeutigkeit in einem Gleichheitsvergleich mit Konstante in dem Bereich gibt, in dem sich vorzeichenbehaftete und vorzeichenlose Versionen des Typs überlappen.

Wenn ich es

if (si == 2147483648U) { printf("xxxx"); }

zu

ändern erhalte ich eine Warnung

(Eigentlich hatte ich -Wextra hinzufügen, bevor ich die Warnungen erhielten Sie berichtete)

0

Chris Dank für Deine Antwort. Ich denke, es führt zur Ursache. Mein ursprünglicher Gedanke war, dass das U-Suffix diese wörtliche verursachen würde zu einem Typ ohne Vorzeichen gefördert werden aber ich denke, dass es nur auf einen Typ ohne Vorzeichen gefördert wird, wenn die Zahl größer als INT_MAX_32 ist, das ist> 2147483647

+0

Es ist in der Tat ' promoted 'to unsigned, aber es gibt keinen Unterschied, wenn sein Wert kleiner als 2^31-1 ist. –

+0

@ryanli: Wenn es immer zu unsigned hochgestuft wird, sollte si == 2U auch eine Warnung ausgeben. Warum ist 2147483647 der magische Punkt, wo gcc mit nur der -Wall-Flagge anfangen sollte, eine Warnung zu werfen. Ich glaube, ich verstehe deine anfängliche Antwort nicht. – nisah

+0

weil '2U' ein Literal ist, und obwohl' si' signiert ist, weiß gcc zur Kompilierzeit klar, dass 'si' mit dem Wert von' 2U' verglichen werden kann, ohne Genauigkeit zu verlieren: wenn 'si' selbst negativ ist , es ist nicht gleich '2U' nach dem Aufstieg auf unsigned. Bei Literalwerten größer als 2^31-1 gibt gcc eine Warnung aus, da "si" gleich dem Literal sein kann, wenn "si" negativ ist, was möglicherweise nicht das Ergebnis ist, was Sie erwartet haben. Und "-Wall" warnt nicht, wie der Link in meiner Antwort zeigt. –

Verwandte Themen