2010-06-11 17 views
16

Tengo la siguiente función para leer una palabra cuádruple-big endian (en un archivo de base abstracta de clase I/O): funcionesConteo de turno error negativo o demasiado grande - ¿solución correcta?

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

El readb() lee un byte. Aquí están los typedefs utilizados:

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

El caso es que me sale 4 advertencias del compilador en las primeras cuatro líneas con la operación de cambio:

advertencia C4293: '< <': valor de desplazamiento negativo o demasiado grande, no definido comportamiento

entiendo por qué se produce esta advertencia, pero me parece que no puede encontrar la manera de deshacerse de él correctamente. Podría hacer algo como:

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

Esto elimina la advertencia, pero ¿no hay ningún otro problema, el BYTE se extenderá correctamente todo el tiempo? Tal vez solo estoy pensando demasiado y la solución es así de simple. ¿Pueden ayudarme aquí? Gracias.

Respuesta

12

Su forma de eliminar la advertencia es correcta. Como probablemente ya sepa, la advertencia se está produciendo porque está tratando de desplazar el contenido de un byte más allá de los límites de una palabra, y luego guárdelo en el quadword. Esta operación no está definida. (Evaluará el lado derecho de la tarea antes de asignar el valor.) Al emitir explícitamente primero, ahora hay suficiente espacio para hacer el cambio, por lo que no hay nada de qué quejarse.

Podría decirse que el compilador debería ser capaz de descubrir que va a almacenarlo en el quadword, por lo que debe asignar primero un quadword y hacer el cambio allí, pero puede no haberse hecho lo suficientemente inteligente como para figurarlo fuera.

Además, no estoy seguro de esto, pero posiblemente compilar esto para x64 tampoco generará la advertencia, ya que una palabra es de 64 bits.

+0

Gracias por su respuesta. Yo mismo pensé que el compilador debería ser lo suficientemente astuto como para ver que lo estoy asignando a una variable lo suficientemente grande como para contener todos los datos (estoy usando MSVS2008). Pero la advertencia generó dudas sobre la corrección de mi código, así que pregunté aquí. – PeterK

+5

Si el compilador se dio cuenta de lo que está haciendo con el resultado y cambia los tipos intermedios en consecuencia, estaría rompiendo el estándar de idioma. La promoción de tipo está bien definida, y el tipo de resultado de un operador solo depende de los tipos de operandos. –

+0

A partir de marzo de 2015, la compilación de dicho código con MSVC 2013 sigue produciendo la advertencia. – Yadli

2

qT | = (unsigned long long) readb() < < (shiftvalue & 63); Esta será la solución perfecta suponiendo que no requirió un cambio de más de 63 bit

+0

y necesita cambios de 56 bits –

Cuestiones relacionadas