2010-06-11 6 views
16

Ich habe die folgende Funktion ein Big-Endian-fach-Wort zum Lesen (in einer abstrakten Basis Datei-I/O-Klasse):Verschiebungszahl negativ oder zu groß Fehler - richtige Lösung?

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; 
} 

Die READB() Funktionen lesen einen BYTE. Hier sind die typedefs verwendet:

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

Die Sache ist, dass ich bekommen 4 Compiler-Warnungen auf den ersten vier Zeilen mit dem Schichtbetrieb:

Warnung C4293: ‚< <‘: Schiebezählwert negativ oder zu groß, undefined Verhalten

ich verstehe, warum diese Warnung auftritt, aber ich kann nicht scheinen, um herauszufinden, wie man es loswerden korrekt. Ich könnte etwas tun wie:

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

Dies entfernt die Warnung, aber gibt es kein anderes Problem, wird das BYTE die ganze Zeit korrekt erweitert? Vielleicht denke ich nur zu viel darüber nach und die Lösung ist so einfach. Kannst du mir hier helfen? Vielen Dank.

Antwort

12

Ihre Art, die Warnung zu entfernen, ist korrekt. Wie Sie wahrscheinlich bereits wissen, tritt die Warnung auf, weil Sie versuchen, den Inhalt eines Bytes über die Grenzen eines Wortes hinaus zu verschieben, dann speichern Sie es im Vierwort. Diese Operation ist nicht definiert. (Es wird die rechte Seite der Zuweisung auswerten, bevor der Wert zugewiesen wird.) Durch das explizite Umwandeln zuerst, ist jetzt genug Platz, um die Verschiebung durchzuführen, also gibt es nichts, worüber man sich beschweren könnte.

Der Compiler sollte in der Lage sein, herauszufinden, dass Sie ihn im Quadwort speichern werden, also sollte er zuerst ein Quadwort zuweisen und die Verschiebung durchführen, aber es wurde möglicherweise nicht intelligent genug gemacht, um es herauszufinden aus.

Auch bin ich mir nicht sicher, aber möglicherweise kompiliert dies für x64 auch nicht die Warnung, wie ein Wort 64 Bits ist?

+0

Vielen Dank für Ihre Antwort. Ich selbst dachte, dass der Compiler klug genug sein sollte, um zu sehen, dass ich ihn einer Variablen zuweise, die groß genug ist, um alle Daten zu halten (ich benutze MSVS2008). Aber die Warnung brachte Zweifel an der Richtigkeit meines Codes, also fragte ich hier. – PeterK

+5

Wenn der Compiler herausgefunden hat, was Sie mit dem Ergebnis machen und die Zwischentypen entsprechend ändern, würde es den Sprachstandard sprengen. Typpromotion ist gut definiert, und der Ergebnistyp eines Operators hängt immer nur von den Operandentypen ab. –

+0

Seit März 2015 erzeugt das Kompilieren eines solchen Codes mit MSVC 2013 immer noch die Warnung. – Yadli

2

qT | = (vorzeichenlos lang lang) readb() < < (shiftvalue & 63); Dies wird die perfekte Lösung sein, vorausgesetzt, Sie brauchen nicht mehr als 63 Bit Verschiebung

+0

und er erfordert 56-Bit-Shifts –