2009-09-01 8 views
1

J'ai une fonction petit échantillon:Comment taper jeter un littéral dans C

#define VALUE 0 

int test(unsigned char x) { 
    if (x>=VALUE) 
    return 0; 
    else 
    return 1; 
} 

Mon compilateur me prévient que la comparaison (x> = VALUE) est vrai dans tous les cas, ce qui est juste, parce que x est un caractère non signé et la valeur est définie avec la valeur 0. donc, j'ai changé mon code pour:

if (((signed int) x) >= ((signed int) VALUE)) 

Mais l'avertissement vient à nouveau. Je l'ai testé avec trois versions de GCC (toutes les versions> 4.0, parfois vous devez activer -Wextra).

Dans le cas modifié, j'ai cette conversion explicite et il doit s'agir d'une comparaison int signée. Pourquoi prétend-elle que la comparaison est toujours vraie?

+0

Alors, qu'essayez-vous d'accomplir? Dans quelles conditions voulez-vous que cela renvoie 1 par opposition à 0? –

+0

Mon intention était d'échapper à cet avertissement. –

+3

Ne partez pas de l'avertissement, essayez de vous débarrasser de votre besoin de savoir si un non signé est> = 0. Il est toujours - c'est ce que le compilateur vous dit. – xtofl

Répondre

9

Même avec la distribution, la comparaison est toujours vraie dans tous les cas de comportement défini. Le compilateur détermine toujours que (signed int)0 a la valeur 0 et détermine quand même que (signed int)x) est non négatif si votre programme a un comportement défini (la conversion de non signé en signé n'est pas définie si la valeur est hors de portée pour le type signé). Par conséquent, le compilateur continue d'émettre des avertissements car il continue d'éliminer totalement le cas else.

Modifier: Pour désactiver l'avertissement, écrivez votre code comme

#define VALUE 0 

int test(unsigned char x) { 
#if VALUE==0 
    return 1; 
#else 
    return x>=VALUE; 
#endif 
} 
+0

Une valeur 'unsigned char' ne peut * jamais * être hors de portée d'un' signed signed '. Même si le bit de signe est défini, la valeur est bien dans la plage d'un 'signed ', et l'opération est toujours bien définie (et le résultat est toujours positif). –

+0

Oups, j'ai raté que c'était de char à int. Pourtant, cela peut arriver sur une implémentation (théorique) de C où sizeof (int) == 1. Étant donné que int doit avoir au moins 2 octets, cela serait possible sur une implémentation où un char est aussi deux octets. Je suis d'accord que sur des plateformes réalistes, aucun débordement ne peut se produire ici. –

1

Le #define de VALUE-0 signifie que votre fonction est réduit à ceci: quel que soit

int test(unsigned char x) { 
    if (x>=0) 
    return 0; 
    else 
    return 1; 
} 

Depuis x est toujours passé en tant unsigned char, il aura toujours une valeur entre 0 et 255 inclus, de si vous avez cast x ou 0 à signed int dans l'instruction if. Le compilateur vous avertit donc que x sera toujours supérieur ou égal à 0, et que la clause else ne peut jamais être atteinte.

11

Je pense que gcc est plus intelligent que vous dans ce cas

3

x est un unsigned char, ce qui signifie qu'il est compris entre 0 et 256 Puisqu'un int est plus grand qu'un char, le unsigned char à signed int conserve la valeur d'origine de char. Puisque cette valeur est toujours> = 0, votre if est toujours vrai.

1

Toutes les valeurs d'un unsigned char peuvent parfaitement s'incorporer dans votre int, donc même avec le plâtre vous n'obtiendrez jamais une valeur négative. Le cast dont vous avez besoin est signed char - cependant, dans ce cas, vous devez déclarer x comme signed dans la signature de la fonction. Il ne sert à rien de dire aux clients que vous avez besoin d'une valeur non signée alors qu'en réalité vous avez besoin d'une signature.

Questions connexes