operadores mascara manipular ejemplos desplazar desplazamiento corrimiento como and c bit-manipulation

mascara - Desplazamiento de bits aritmético en un entero con signo



mascara de bits en c (4)

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

Para simplificar, 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, encontré que: << cambiará hacia MSB (a la izquierda, en mi caso), y rellenará bits LSB "vacíos" con 0s.

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

Entonces, x = x << 7 dará como resultado el movimiento de LSB a MSB y el ajuste de todo a 0s.

1000.0000

Ahora, digamos que lo haría >> 7 , último resultado. Esto daría como resultado [0000.0010] ? ¿Estoy en lo cierto?

¿Estoy en lo cierto sobre 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é?


Como otros dijeron, el cambio del valor negativo está definido por la implementación.

La mayoría de las implementaciones tratan el desplazamiento a la derecha como piso (x / 2 N ) llenando desplazado en bits usando el bit de signo. Es muy conveniente en la práctica, ya que esta operación es muy común. Por otro lado, si cambiará a la derecha el entero sin signo, el desplazamiento en bits se pondrá a cero.

Mirando desde el lado de la máquina, la mayoría de las implementaciones tienen dos tipos de instrucciones shift-right:

  1. Un desplazamiento ''aritmético'' (a menudo tiene ASN mnemotécnico o SRA) que funciona como yo lo explico.

  2. Un derecho de cambio ''lógico'' (el sistema tiene LSN mnemotécnico o SRL o SR) que funciona como usted espera.

La mayoría de los compiladores utilizan primero para los tipos firmados y el segundo para los no firmados. Solo por conveniencia


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 cambiar en ceros, dependiendo de 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 negativamente o la operación de cambio desplazará un 1 hacia o más allá del bit de signo, tiene un comportamiento indefinido (como lo hacen la mayoría de las operaciones en valores firmados que causan un desbordamiento).

(Un comportamiento indefinido significa que podría suceder cualquier cosa.)

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


En el compilador de 32 bits

x = x >> 31;

aquí x es el entero con signo, por lo tanto, el bit 32 es el bit de signo.

el valor x final es 100000 ... 000 . y el 32º bit indica el valor -ivo.

aquí x valor implementar al cumplido de 1.

entonces la x final es -32768


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

para ''<<''

6.5.7 / 4 [...] Si E1 tiene un tipo firmado 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 firmado 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 con signo en una implementación específica, porque no tiene garantía de que funcionará de la misma manera en cualquier otra implementación (una implementación es, por ejemplo, compilador en su computadora con su parámetros específicos de línea de comunicación).

Puede que ni siquiera funcione para una versión anterior o más nueva del mismo compilador. El compilador incluso podría 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 usa en todas las fuentes o incluso depender de cosas como la optimización de ensamblaje u otro uso de registro. Si está encapsulado en una función, es posible que ni siquiera produzca el mismo resultado en esos bits en dos llamadas consecutivas con los mismos argumentos.

Teniendo en cuenta únicamente los valores no negativos , el efecto del desplazamiento a la izquierda en 1 ( expression << 1 ) es lo mismo que multiplicar la expresión por 2 (siempre que la expresión * 2 no se desborde) y el efecto de desplazamiento a la derecha en 1 ( expression >> 1 ) es lo mismo que dividir por 2.