2010-06-11 10 views
16

Mam następujący funkcja czytania big-endian poczwórne (w abstrakcyjnym pliku bazowego I/O) klasy: funkcjeBłąd przesunięcia jest ujemny lub zbyt duży - poprawne rozwiązanie?

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

readb() odczytuje bajt. Oto typedefs używane:

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

Chodzi o to, że ja się 4 ostrzeżenia kompilatora na pierwszych czterech linii z pracy zmianowej:

ostrzeżenie C4293: „< <”: Ilość przesunięcie ujemny lub zbyt duże, niezdefiniowana zachowanie

rozumiem dlaczego występuje to ostrzeżenie, ale nie wydaje się dowiedzieć się, jak się go pozbyć poprawnie. Mogłem zrobić coś takiego:

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

Powoduje usunięcie ostrzeżenia, ale czy nie ma żadnego innego problemu, czy urządzenie BYTE będzie prawidłowo przedłużane przez cały czas? Może po prostu o tym myślę za dużo, a rozwiązanie jest takie proste. Czy możecie mi pomóc? Dzięki.

Odpowiedz

12

Twój sposób usunięcia ostrzeżenia jest poprawny. Jak już zapewne wiesz, ostrzeżenie występuje, ponieważ próbujesz przesunąć zawartość bajtu poza granice słowa, , a następnie zapisać je w quadword. Ta operacja jest niezdefiniowana. (Oceni prawą stronę zadania przed przypisaniem wartości.) Przez wyraźne rzutowanie najpierw jest wystarczająco dużo miejsca, aby wykonać przesunięcie, więc nie ma na co narzekać.

Możliwe, że kompilator powinien być w stanie stwierdzić, że zamierzasz zapisać go w quadrze, więc powinien najpierw przydzielić czwarte słowo i wykonać tam przesunięcie, ale może nie być wystarczająco inteligentny, aby go zrozumieć. na zewnątrz.

Ponadto, nie jestem tego pewien, ale prawdopodobnie kompilacja tego dla x64 również nie wygeneruje ostrzeżenia, ponieważ jedno słowo ma 64 bity?

+0

Dziękuję za odpowiedź. Sam myślałem, że kompilator powinien być wystarczająco sprytny, aby zobaczyć, że przypisuję go do zmiennej wystarczająco dużej, aby pomieścić wszystkie dane (używam MSVS2008). Ale ostrzeżenie budziło wątpliwości co do poprawności mojego kodu, więc zapytałem tutaj. – PeterK

+5

Jeśli kompilator zorientował się, co robisz z wynikiem i odpowiednio zmienia typy pośrednie, złamałoby to standard językowy. Promocja typu jest dobrze zdefiniowana, a typ wyniku operatora zależy tylko od typów argumentów. –

+0

Od marca 2015 r. Kompilacja takiego kodu z MSVC 2013 nadal generuje ostrzeżenie. – Yadli

2

qT | = (unsigned long long) readb() < < (shiftvalue & 63); To będzie idealne rozwiązanie, zakładając, że nie potrzebujesz więcej niż 63-bitowej zmiany

+0

, a także wymaga 56-bitowych zmian –

Powiązane problemy