2009-10-29 8 views
4

Je construis mon projet avec le drapeau d'avertissement -Wconversion de GCC. (gcc (Debian 4.3.2-1.1) 4.3.2) sur un système d'exploitation/matériel GNU/Linux 64 bits. Je trouve cela utile d'identifier où j'ai mélangé les types ou perdu la clarté quant aux types qui devraient être utilisés.Comment gérer les avertissements -Wconversion de GCC?

Ce n'est pas utile dans la plupart des autres situations qui activent c'est des avertissements et je demande comment suis-je censé faire face à ces:

enum { A = 45, B, C }; /* fine */ 

char a = A;    /* huh? seems to not warn about A being int. */ 
char b = a + 1;   /* warning converting from int to char */ 
char c = B - 2;   /* huh? ignores this *blatant* int too.*/ 
char d = (a > b ? b : c) /* warning converting from int to char */ 

En raison des résultats inattendus des essais ci-dessus (cas a et c) Je demande également que ces différences soient également expliquées.

Éditer: Et est-ce trop de génie pour lancer tous ces éléments avec (char) pour empêcher l'avertissement?

Edit2: Certains cas supplémentaires (à la suite des cas ci-dessus):

a += A;   /* warning converting from int to char */ 
a++;   /* ok */ 
a += (char)1; /* warning converting from int to char */ 

En dehors de cela, ce que je demande est subjective et j'aimerais entendre comment les gens traitent les avertissements de conversion dans des cas comme ceux-ci lorsque vous considérez que certains développeurs préconisent de supprimer tous les avertissements.

YAE:

Une solution possible est d'utiliser simplement int s au lieu de char s droit? En fait, non seulement cela nécessite plus de mémoire, mais c'est aussi plus lent, comme le démontre le code suivant. Les expressions mathématiques sont juste là pour obtenir les avertissements lorsqu'il est construit avec -Wconversion. Je suppose que la version utilisant char variables serait plus lente que celle en utilisant int s en raison des conversions, mais sur mon (64bit dual core II) système la version int est plus lente.

#include <stdio.h> 

#ifdef USE_INT 
typedef int var; 
#else 
typedef char var; 
#endif 

int main() 
{ 
    var start = 10; 
    var end = 100; 
    var n = 5; 
    int b = 100000000; 
    while (b > 0) { 
     n = (start - 5) + (n - (n % 3 ? 1 : 3)); 
     if (n >= end) { 
      n -= (end + 7); 
      n += start + 2; 
     } 
     b--; 
    } 
    return 0; 
} 

passe -DUSE_INT à gcc pour construire la version int de l'extrait ci-dessus.

+2

Que dit-il lorsque vous compilez avec A> 255? –

+1

avec 'A = 256'" avertissement: débordement dans la conversion constante implicite "pour' char a = A' et "avertissement: la conversion en 'char' modifie 'int' valeur constante" pour 'char c = B - 2' –

Répondre

2

Lorsque vous dites /* int */, voulez-vous dire qu'il vous avertit à ce sujet? Je ne vois aucun avertissement dans ce code avec gcc 4.0.1 ou 4.2.1 avec -Wconversion. Le compilateur convertit ces énumérations en constantes. Puisque tout est connu au moment de la compilation, il n'y a aucune raison de générer un avertissement. Le compilateur peut optimiser toutes les incertitudes (ce qui suit est Intel avec 4.2.1):

movb $45, -1(%rbp) # a = 45 
    movzbl -1(%rbp), %eax 
    incl %eax 
    movb %al, -2(%rbp) # b = 45 + 1 
    movb $44, -3(%rbp) # c = 44 (the math is done at compile time) 
    movzbl -1(%rbp), %eax 
    cmpb -2(%rbp), %al 
    jle  L2    
    movzbl -2(%rbp), %eax 
    movb %al, -17(%rbp) 
    jmp  L4 
L2: 
    movzbl -3(%rbp), %eax 
    movb %al, -17(%rbp) 
L4: 
    movzbl -17(%rbp), %eax 
    movb %al, -4(%rbp) # d = (a > b ? b : c) 

Ceci est sans activer les optimisations. Avec les optimisations, il calculera b et d pour vous au moment de la compilation et codera en dur les valeurs finales (s'il en a vraiment besoin pour quelque chose). Le fait est que gcc a déjà compris qu'il ne peut y avoir de problème ici car toutes les valeurs possibles correspondent à char.

EDIT: Permettez-moi de modifier cela un peu. Il y a une erreur possible dans l'affectation de b, et le compilateur ne l'attrapera jamais, même si c'est certain. Par exemple, si b=a+250;, il sera certain que débordera b mais gcc n'émettra pas d'avertissement.C'est parce que l'affectation à a est légale, a est un char, et c'est votre problème (pas celui du compilateur) de s'assurer que les maths ne débordent pas lors de l'exécution.

+0

Ajout d'informations sur la version de GCC (4.3.2) –

+0

Donc, ce que vous dites est que dans 4.3, ils ont corrigé le morceau que j'ai appelé "le compilateur ne l'attrapera jamais". Donc, dans les cas où une constante est utilisée, il n'y a pas d'avertissement, mais si vous faites des calculs qui pourraient déborder l'omble, ils préviennent. On dirait que ça marche bien, alors. Y a-t-il encore un problème? –

+0

Le problème n'était pas tellement de vouloir attraper les débordements - mon code est déjà testé et à portée. La question principale n'était pas non plus de savoir pourquoi certains des exemples ont suscité des avertissements alors que d'autres ne l'ont pas fait. Le problème est avec la philosophie "Fixer tous les avertissements" que j'ai tendance à vouloir atteindre, mais dans le cas du drapeau -Wconversion, il semble complètement OTT d'encombrer la plus simple des expressions avec des conversions. C'était dans ce domaine que je voulais entendre les points de vue des gens. –

0

Peut-être que le compilateur peut déjà voir que toutes les valeurs tiennent dans un caractère de sorte qu'il ne dérange pas l'avertissement. Je m'attendrais à ce que le enum soit résolu dès le début de la compilation.

+0

à propos du cas de l'opérateur ternaire? Comment cela peut-il avoir un sens? –

+0

Je pense que cela peut être résolu par le compilateur de sorte qu'il met simplement 'd = 44'. –

Questions connexes