2011-02-09 9 views
53

¿Qué sucede exactamente aquí?Cambio a la izquierda con un recuento de cambio negativo

a << -5

Obviamente no lo hace desplazamiento a la derecha. Pero el libro que estoy leyendo: estados

en una máquina, esta expresión hace realidad una desviación a la izquierda de 27 bits

Mi pregunta es; ¿por qué? ¿Qué causa un desplazamiento a la izquierda de 27 bits? ¿Y qué ocurre exactamente al cambiar con un recuento de turno negativo? Gracias.

Respuesta

63

enteros negativos en el lado derecho es un comportamiento indefinido en el lenguaje C.

ISO 9899: 1999 6.5.7 operadores de desplazamiento de bit § 3.

Las promociones enteros se realizan en cada uno de los operandos. El tipo de el resultado es el del operando izquierdo promocionado. Si el valor del operando derecho es negativo o es mayor que o igual a la anchura de el operando de la izquierda promovido, el comportamiento es indefinido.

+23

Por cierto, si su libro no menciona que este es un comportamiento indefinido, debería considerar obtener otro libro. – Lundin

+1

Dependiendo de lo que diga el libro, podría argumentar que esto es exactamente lo que estaba diciendo (aunque podría ser más claro). "En una máquina, algo sucede" implícitamente significa que podría no suceder en otros. – 3Doubloons

+0

Si esto no funciona, ¿sería alguna operación que tendría un comportamiento equivalente al comportamiento deseado en la pregunta? Parece algo triste tener que escribir una ecuación para esta operación en particular :(. Intento hacer un cambio a la derecha que hace que 1 sea 0. – patrik

11

El comportamiento no está definido.

En la aritmética binaria de 5 bits, two's-complement -5 tiene la misma representación binaria que el signo sin signo +27, lo que probablemente explica esa plataforma en particular.

+0

es la aritmética binaria de 5 bits una cosa real? ¿Cómo se definiría Char? – CIsForCookies

+2

@ClsForCookies: a nivel eléctrico, es algo real. No hay nada especial en 8. –

1

Si el valor que está cambiando es una variable de 32 bits, el desplazamiento -5 va en un "bucle" y desplaza 27 hacia adelante. El cambio solo puede tener lugar de forma "sin firmar".

+0

Pero si la variable de 32 bits está firmada, las promociones enteras no cambiarán la firma de -5. Y luego el comportamiento no está definido y el programa es libre de detenerse y prenderse fuego. – Lundin

+0

probablemente. De todos modos, creo que es una mala práctica :) – arnorhs

16

Como ya han respondido otros miembros, produce un comportamiento indefinido. Lo que me gustaría mencionar aquí es que citas del libro ("En una máquina") parece ser parcial. No generaliza el comportamiento. El libro también podría haber explicado que el comportamiento no está definido según el estándar. Por cierto, me acaba de pasar por "La nueva C Standard - Un Económico y comentario cultural" y considera esta declaración:

La SAL instrucciones Intel Pentium (generada por tanto gcc y Microsoft C++ para evaluar izquierda turnos) sólo utiliza los cinco últimos bits del cambio cantidad

Esta muy bien explica por qué una desviación a la izquierda de -5 podría resultar en un desplazamiento a la izquierda de 27 (para la representación de complemento a 2 de los números negativos)

+3

Estoy seguro de que la oración "En una máquina" en el libro de OP solo sirve como un ejemplo, justo después de afirmar que esto no está definido. En realidad, es uno de los buenos ejemplos de que "indefinido" realmente significa cualquier cosa, y no solo la terminación abrupta "limpia" del programa en ejecución.Si se usa de esta manera, no tendría sentido dar la impresión de que el desplazamiento a la izquierda por 27 es algo que usted tiene derecho a esperar. –

+0

+1 para responder a la parte de la pregunta "¿Qué ocurre exactamente [en la citada" máquina "] cuando se cambia con un recuento de cambios negativo". seguro, UB es UB, por lo que no deberíamos suponer nada al respecto, pero esta explicación es extremadamente ilustrativa del tipo de peligros que los llevaron a hacerlo. (Mi cerebro siempre quiere decir "pero ¿por qué no se puede definir por enteros literales?", pero luego pienso más y me doy cuenta de que es absurdo ;-) –

0
int main() 
{ 
    unsigned int a = 1; 
    printf("%u\n",a<<(-1)); 
    return 0; 
} 

La salida es 2147483648.

Aquí es mi suposición y validación: (solo suposición)

1.El "< <" operando derecho debe ser sin signo de tipo int,

así en primer lugar, la (int) “-1” serán arrojados al (unsigned int) "-1". Causa tipo int es una representación de complemento a dos, el resultado será 2^32-1 (sin signo int)

2.Debido al número 2^32-1 es mayor que el dígito de desplazamiento máximo, 2^32 - 1 será mod 32, lo que equivale a 27

también intentado algunos otros números nagetive operando derecho, y los resultados de cálculo manuales con reglas assumpted serán los mismos con qué producto por mi IDE.

Estoy tratando de encontrar algunos documentos oficiales de apoyo, que puedan verificar si mi suposición es correcta o no. Tal vez usted me puede decir.

Cuestiones relacionadas