2010-02-28 20 views
12

J'ai un tableau suivant, que j'ai besoin de manipuler à la main sur les bitmaps.C++: Avertissement du compilateur pour les entiers intenses non signés

const unsigned int BITS[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 
           2048, 4096, 8192, 16384, 32768, 65536, 131072, 
           262144, 524288, 1048576, 2097152, 4194304, 
           8388608, 16777216, 33554432, 67108864, 134217728, 
           268435456, 536870912, 1073741824, 2147483648}; 

Malheureusement, lors de la compilation je reçois

Avertissement: ce que dans ISO C90

est constante décimale non signée

Comment puis-je supprimer ce?

+0

Voir cette question similaire: http://stackoverflow.com/questions/2347936/cant-get-ride-of-this-decimal-constant -is-unsigned-only-in-iso-c90-warning –

+0

Pourquoi faites-vous cela? Si vous pensez qu'une table de consultation va être plus rapide que de simplement calculer ces valeurs comme nécessaire, détrompez-vous ... – Nemo

Répondre

15

Les littéraux entiers en C sont, par défaut, de type "signed int" (éditer: mais voir les commentaires sur les mises en garde). Le dernier numéro est trop grand pour être représenté comme un entier signé 32 bits, et donc vous devez dire au compilateur que c'est un entier non signé en suffixant avec « U », comme:

2147483648U 

Notez que vous pouvez également ajouter un suffixe de "L" pour en faire un "long", mais sur de nombreux systèmes qui est toujours en 32 bits et donc sans importance.

En outre, il y a un moyen de beaucoup moins sujette aux erreurs (et à lire plus facile) écrire ce code, avec l'opérateur décalage binaire:

const unsigned int BITS[32] = {1U, 1U<<1, 1U<<2, 1U<<3, 1U<<4, 
           /* and so on */ 
           1U<<31}; 

Ou, écrit en hexadécimal, si vous ne Pas de décalage de bits pour une raison quelconque:

const unsigned int BITS[32] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 
           /* and so on */ 
           0x80000000U}; 
+0

Pourquoi le compilateur le traite-t-il alors comme un int, plutôt que de le transformer automatiquement en uint? Surtout, qu'il sait exactement dans quel type il sera stocké. – gruszczy

+0

Dans de nombreux cas, vous ne pouvez pas savoir quel type est une constante (par exemple, en tant qu'argument de fonction dans une fonction varargs), il doit donc être spécifié explicitement. Il est déroutant d'avoir le type implicite à certains moments et doit être spécifié explicitement dans d'autres, et aussi déroutant d'avoir la même constante être de différents types sur des systèmes avec des tailles int différentes. De plus, parce que C ne fait jamais d'inférence de type de ce genre, l'ajouter pour ce cas compliquerait beaucoup l'analyseur sans bénéfice significatif. –

+3

@gruszczy: Dans C89/90, une constante décimale non suffixée doit être interprétée comme suit: int, long ou unsigned long (selon la première éventualité). En C99, il doit être interprété comme «int», «long» ou «long long» (selon celui qui convient le premier). C'est ce que le compilateur essaie de dire par cet avertissement. Apparemment, sur cette plate-forme 'long' a la même taille que' int'. Le compilateur dit en gros: "peut-être que vous essayiez de créer une constante connectée longue ou peut-être même longue, mais par les règles de C89/90 je dois la faire' non signé long. " – AnT

6

Votre constante doit être spécifiée comme trop non signé, utilisez

2147483648UL 

(UL = unsigned long), ou tout simplement

2147483648U 

pour un entier non signé.

Comme votre code est maintenant, une constante, qui est par défaut un simple int, et donc signé, est affectée à un unsigned int, ce qui génère votre avertissement.

+0

Cela a fonctionné, merci beaucoup :-) – gruszczy

+3

Pandandically parlant, l'erreur n'est pas que du fait de la (plaine int) constante est affectée à un int non signé; la cession est sans importance. L'erreur est que la valeur de "2147483648" est trop grande pour être un int signé, et il y a donc un débordement dans la génération de la constante int signée en premier lieu. –

+2

En fait, la véritable raison de l'avertissement est que le compilateur doit choisir 'unsigned long' pour le type constant. (Note, encore une fois, cette constante n'est pas 'unsigned int', elle est' unsigned long'.) Et elle doit le choisir en C89/90 spécifiquement, au lieu de choisir un plus grand type signé (qu'il pourrait supporter) ou suivant C99 règles et en choisissant 'long long'. C'est ce sur quoi porte l'avertissement et pourquoi il se réfère à 'ISO C90'. En C99, par exemple, une constante décimale non suffixée ne recevrait jamais un type non signé. – AnT

1

Il n'est pas nécessaire de définir le type de données comme étant simplement non signé;

int variable_name=2147483648U; 

autre simplement convertir la valeur décimale en hexadécimal ...