Desplazamiento de bits aritmético en un entero con signo

Resuelto newprint asked hace 14 años • 6 respuestas

Estoy tratando de descubrir cómo funcionan exactamente los operadores aritméticos de desplazamiento de bits en C y cómo afectarán a los enteros de 32 bits con signo.

Para simplificar las cosas, digamos que trabajamos dentro de un byte (8 bits):

x = 1101.0101
MSB[ 1101.0101 ]LSB

Al leer otras publicaciones en Stack Overflow y algunos sitios web, descubrí que: <<se desplazará hacia MSB (a la izquierda, en mi caso) y llenará los bits LSB "vacíos" con 0.

Y >>se desplazará hacia LSB (a la derecha, en mi caso) y llenará los bits "vacíos" con el bit MS.

Por lo tanto, x = x << 7resultará en mover LSB a MSB y establecer todo en 0.

1000.0000

Ahora, digamos que obtendría su >> 7último resultado. Esto resultaría en [0000.0010]? ¿Estoy en lo cierto?

¿Estoy en lo cierto acerca de mis suposiciones sobre los operadores de turnos?

Acabo de probar en mi máquina, **

int x = 1;   //000000000......01

x = x << 31; //100000000......00

x = x >> 31; //111111111......11 (Everything is filled with 1s !!!!!) 

¿Por qué?

newprint avatar Oct 25 '10 02:10 newprint
Aceptado

El desplazamiento a la derecha de un número con signo negativo tiene un comportamiento definido por la implementación.

Si sus 8 bits están destinados a representar un valor de 8 bits con signo (ya que está hablando de un "entero de 32 bits con signo" antes de cambiar a ejemplos de 8 bits), entonces tiene un número negativo. Desplazarlo hacia la derecha puede llenar bits "vacíos" con el MSB original (es decir, realizar una extensión de signo) o puede desplazarse en ceros, según la plataforma y/o el compilador.

(El comportamiento definido por la implementación significa que el compilador hará algo sensato, pero de una manera dependiente de la plataforma; se supone que la documentación del compilador le dirá qué).


Un desplazamiento a la izquierda, si el número comienza siendo negativo, o si la operación de desplazamiento desplazaría un 1 hacia o más allá del bit de signo, tiene un comportamiento indefinido (al igual que la mayoría de las operaciones con valores con signo que provocan un desbordamiento).

(El comportamiento indefinido significa que podría pasar cualquier cosa).


Las mismas operaciones con valores sin signo están bien definidas en ambos casos: los bits "vacíos" se rellenarán con 0.

Matthew Slattery avatar Oct 24 '2010 19:10 Matthew Slattery

Las operaciones de desplazamiento bit a bit no están definidas para valores negativos

para '<<'

6.5.7/4 [...] Si E1 tiene un tipo con signo y un valor no negativo, y E1×2 E2 es representable en el tipo de resultado, entonces ese es el valor resultante; de lo contrario, el comportamiento no está definido.

y para '>>'

6.5.7/5 [...] Si E1 tiene un tipo con signo y un valor negativo, el valor resultante está definido por la implementación.

Es una pérdida de tiempo estudiar el comportamiento de estas operaciones en números firmados en una implementación específica, porque no hay garantía de que funcione de la misma manera en cualquier otra implementación (una implementación es, por ejemplo, el compilador de su computadora con su parámetros específicos de la línea de comandos).

Es posible que ni siquiera funcione para una versión anterior o nueva del mismo compilador. El compilador podría incluso definir esos bits como aleatorios o indefinidos. Esto significaría que la misma secuencia de código podría producir resultados totalmente diferentes cuando se use en todas sus fuentes o incluso depender de cosas como la optimización del ensamblaje u otro uso de registros. Si se encapsula en una función, es posible que ni siquiera produzca el mismo resultado en esos bits en dos llamadas consecutivas con los mismos argumentos.

Considerando solo valores no negativos , el efecto de desplazar a la izquierda en 1 ( expression << 1) es el mismo que multiplicar la expresión por 2 (siempre que la expresión * 2 no se desborde) y el efecto de desplazar a la derecha en 1 ( expression >> 1) es el mismo que dividir entre 2.

pmg avatar Oct 24 '2010 19:10 pmg

A partir de C++20, los operadores de desplazamiento bit a bit para enteros con signo están bien definidos.

El desplazamiento a la izquierda a<<bequivale al a*2^bmódulo 2^N, donde Nes el número de bits del tipo resultante. En particular, 1<<31es de hecho el intvalor más pequeño.

El desplazamiento a la derecha a>>bequivale a a/2^b, redondeado hacia abajo (es decir, hacia el infinito negativo). Entonces, por ejemplo -1>>10 == -1.

Para obtener más detalles, consulte https://en.cppreference.com/w/cpp/language/operator_arithmetic .

(para los estándares más antiguos, consulte la respuesta de Matthew Slattery)

example avatar May 07 '2019 15:05 example