2012-01-03 14 views
7

Estoy obteniendo resultados del turno de la izquierda al que no pude encontrar una explicación.Por qué el resultado de char sin signo << char sin signo no está sin signo char

unsigned char value = 0xff; // 1111 1111 
unsigned char = 0x01; // 0000 0001 

std::cout << "SIZEOF value " << sizeof(value) << "\n"; // prints 1 as expected 
std::cout << "SIZEOF shift " << sizeof(shift) << "\n"; // prints 1 as expected 

std::cout << "result " << (value << shift) << "\n"; // prints 510 ??? 

std::cout << "SIZEOF result " << sizeof(value << shift) << "\n"; // prints 4 ??? 

que estaba esperando resultado sea 1111 1110 pero en cambio me sale int (?) Con el valor de 1 1111 1110.

¿Cómo se pueden desplazar los bits de un carácter sin signo hacia la izquierda para que los bits se trunquen y el resultado sea 1111 1110?

Lo que trato de hacer es leer series de bytes e interpretarlas como enteros de longitudes variables (1-32 bits).

F0  F5 
1111 0000 1111 0101 

podría ser

0F (first 4 bits) 
0F (next 8 bits) 
05 (last 4 bits) 

Tiene esto algo que ver con el hecho de que la aritmética no se hace con los tipos más pequeños que int?

+0

11111111 << 1 es de hecho 111111110, está imprimiendo el resultado de la expresión, intente hacer: 'value = value << shift;' y luego 'cout << value;' – Yaniro

Respuesta

9

Citando algunos borrador de la norma 2011:

5,8 Shift operadores [expr.shift]

...

Los operandos deben ser del tipo de enumeración integral o no y se deben realizar promociones integrales. El tipo de resultado es el del operando izquierdo promocionado.

y

4.5 Promociones Integrales [conv.prom]

A prvalue de un tipo entero distinto de bool, char16_t, char32_t, o wchar_t cuyo número entero de conversión rango (4,13) es menor que el rango de int se puede convertir a un prvalue de tipo int si int puede representar todos los los valores del tipo de fuente; de lo contrario, la fuente prvalue se puede convertir en un prvalue de tipo unsigned int

...

Así, se promueve a valueint, y el tipo de value << shift es el tipo del operando izquierdo promovido , es decir, int.

que puede lograr el resultado deseado una de estas formas:

std::cout << "result " << ((unsigned char)(value << shift)) << "\n"; 
std::cout << "result " << ((value << shift)&0xff) << "\n"; 
2

Sólo echarlo de nuevo a un unsigned char:

std::cout << "result " << static_cast<unsigned char>(value << shift) << "\n"; 

O bien, utilizar bit a bit-Y:

std::cout << "result " << ((value << shift) & 0xFF) << "\n"; 
2

Se podría enmascarar los bits que le interesa:

(value << shift) & 0xff 

Lo que está viendo es el resultado de la promoción número entero y es parte del lenguaje. Imagina que estás componiendo un entero de 16 bits a partir de 2 bits de 8 bits: no te gustaría promocionar manualmente un entero de mayor ancho para colocar los bits altos y bajos en el lugar correcto, ¿verdad?

Cuestiones relacionadas