2010-06-11 12 views
16

Ho la seguente funzione per la lettura di un big-endian quadword (in un file di base astratta classe I/O): funzioniErrore di conteggio negativo o troppo grande - soluzione corretta?

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

Il readb() Legge un byte. Ecco le typedef usati:

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

Il fatto è che ottengo 4 avvisi del compilatore sulle prime quattro righe con l'operazione di spostamento:

avvertimento C4293: '< <': valore di scorrimento negativo o troppo grandi, non definito comportamento

capisco perché si verifica questo avvertimento, ma io non riesco a capire come sbarazzarsi di esso correttamente. Potrei fare qualcosa del tipo:

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

Questo rimuove l'avviso, ma non ci sono altri problemi, il BYTE sarà correttamente esteso per tutto il tempo? Forse ci sto pensando troppo e la soluzione è così semplice. Ragazzi, potete aiutarmi qui? Grazie.

risposta

12

Il modo di rimuovere l'avviso è corretto. Come probabilmente già saprai, l'avviso si sta verificando perché stai cercando di spostare il contenuto di un byte oltre i limiti di una parola, quindi memorizzalo nella quadword. Questa operazione non è definita. (Valuterà il lato destro del compito prima di assegnare il valore.) Eseguendo il casting esplicito per primo, ora c'è abbastanza spazio per fare il turno, quindi non c'è nulla di cui lamentarsi.

Probabilmente, il compilatore dovrebbe essere in grado di capire che lo memorizzerete nella quadword, quindi dovrebbe allocare prima una quadrupla e fare il turno lì, ma potrebbe non essere stata resa abbastanza intelligente da capirlo su.

Inoltre, non sono sicuro di questo, ma probabilmente la compilazione di questo per x64 non genererà l'avviso, in quanto una parola è 64 bit?

+0

Grazie per la risposta. Io stesso pensavo che il compilatore dovesse essere abbastanza intelligente da vedere che lo sto assegnando a una variabile abbastanza grande da contenere tutti i dati (sto usando MSVS2008). Ma l'avvertimento ha messo in dubbio la correttezza del mio codice, quindi ho chiesto qui. – PeterK

+5

Se il compilatore ha capito cosa si sta facendo con il risultato e si modifica di conseguenza i tipi intermedi, si rompe lo standard della lingua. La promozione del tipo è ben definita e il tipo di risultato di un operatore dipende sempre solo dai tipi di operandi. –

+0

A partire da marzo 2015, la compilazione di tale codice con MSVC 2013 produce ancora l'avviso. – Yadli

2

qT | = (senza firma lunga lunga) readb() < < (valore di spostamento & 63); Questa sarà la soluzione perfetta presumendo di non aver richiesto più di 63 bit shift

+0

e richiede spostamenti a 56 bit –

Problemi correlati