2010-06-11 19 views
16

J'ai la fonction suivante pour lire un quadword big-endian (dans un fichier de base abstraite de classe I/O):Décalage négatif ou erreur trop importante - solution correcte?

unsigned long long File::readBigEndQuadWord(){ 
    unsigned long long qT = 0; 
    qT |= readb() << 56; 
    qT |= readb() << 48; 
    qT |= readb() << 40; 
    qT |= readb() << 32; 
    qT |= readb() << 24; 
    qT |= readb() << 16; 
    qT |= readb() << 8; 
    qT |= readb() << 0; 
    return qT; 
} 

Les fonctions readb() lit un BYTE. Voici les typedefs utilisés:

typedef unsigned char BYTE; 
typedef unsigned short WORD; 
typedef unsigned long DWORD; 

La chose est que je reçois 4 avertissements du compilateur sur les quatre premières lignes avec l'opération de changement:

avertissement C4293: « < < »: compte de décalage négatif ou trop grand, le comportement non défini

Je comprends pourquoi cet avertissement se produit, mais je ne peux pas sembler comprendre comment se débarrasser correctement. Je pourrais faire quelque chose comme:

qT |= (unsigned long long)readb() << 56;

Cela supprime l'avertissement, mais n'y a-t-il pas d'autres problèmes, le BYTE sera-t-il correctement étendu tout le temps? Peut-être que je n'y pense que trop et que la solution est aussi simple. Pouvez-vous m'aider ici? Merci.

Répondre

12

Votre façon de supprimer l'avertissement est correcte. Comme vous le savez probablement déjà, l'avertissement se produit parce que vous essayez de déplacer le contenu d'un octet au-delà des limites d'un mot, puis le stocker dans le quadword. Cette opération est indéfinie. (Il évaluera le côté droit de la tâche avant d'attribuer la valeur.) En jetant explicitement le premier, il y a maintenant assez d'espace pour faire le changement, donc il n'y a rien à redire. On peut dire que le compilateur devrait être capable de comprendre que vous allez le stocker dans le quadword, donc il devrait d'abord allouer un quadword et faire le décalage, mais il n'a peut-être pas été assez intelligent pour le comprendre en dehors.

En outre, je ne suis pas sûr à ce sujet, mais éventuellement compiler ceci pour x64 ne générera pas non plus l'avertissement, comme un mot est 64 bits?

+0

Merci pour votre réponse. J'ai moi-même pensé que le compilateur devrait être assez intelligent pour voir que je l'attribue à une variable assez grande pour contenir toutes les données (j'utilise MSVS2008). Mais l'avertissement a soulevé des doutes sur l'exactitude de mon code, alors j'ai demandé ici. – PeterK

+5

Si le compilateur a compris ce que vous faites avec le résultat et change les types intermédiaires en conséquence, alors il viole la norme du langage. La promotion de type est bien définie et le type de résultat d'un opérateur dépend uniquement des types d'opérandes. –

+0

En mars 2015, la compilation d'un tel code avec MSVC 2013 produisait toujours l'avertissement. – Yadli

2

qT | = (unsigned long long) readb() < < (valeur de décalage & 63); Ce sera la solution parfaite en supposant que vous n'avez pas besoin de plus de 63 bits de décalage

+0

bien qu'il nécessite des quarts de 56 bits –