2009-06-21 9 views
8

que estaba escaneando un código de tercera fuente del partido usando Findbugs (sólo para ser cautos antes de integrar en él la mía), y se encontró la siguiente advertencia:Advertencia de Findbugs: Entero shift por 32 - ¿qué significa?

long a = b << 32 | c 

Bug: Entero desplazamiento por id 32 Patrón: ICAST_BAD_SHIFT_AMOUNT , tipo: BDesplace, categoría: CORRECCIÓN

el código realiza un cambio de número entero por una cantidad constante fuera de la gama 0..31. El efecto de esto es usar los 5 bits más bajos del valor entero para decidir cuánto mover. Es probable que no se quiera y sea al menos confuso.

¿Podría alguien explicar qué significa exactamente lo anterior?

Gracias! (soy bastante novato en programación Java)

Respuesta

30

Desde el Java Language Specification:

Si el tipo promovido del operando de la izquierda es de tipo int, sólo los cinco bits de orden inferior del operando de la derecha se utilizan como la distancia de desplazamiento. Es como si el operando de la derecha estuviera sujeto a un operador AND lógico a nivel de bit & (§15.22.1) con el valor de máscara 0x1f. Por lo tanto, la distancia de desplazamiento realmente utilizada está siempre en el rango de 0 a 31, inclusive.

Así que si b es un entero, la expresión es idéntica a

long a = b | c; 

la que me altamente duda es lo que se pretende. Probablemente debería haber sido

long a = ((long) b << 32) | c; 

(b Si ya es mucho, el código es correcto y FindBugs es errónea acerca del fallo).

+0

Entonces,' int >> 32 (0x100000) == int >> 0 (0x00000) '? –

+1

Pseudo-sintaxis extraña que usa, pero sí, eso es todo. – UndefinedBehavior

5

Editado: El problema es casi seguro que se deriva del hecho de que 'b' es un 'int' y no un 'largo'.

En C, si 'b' es un número entero en vez de largo y se desplaza a la izquierda en 32 bits, todos los bits del valor original se han eliminado, por lo que el resultado de la expresión general sería el mismo 'c' se invoca un comportamiento indefinido, por lo que cualquier resultado es permisible. Java define las cosas de manera diferente, como se señala en el comentario de Rasmus Faber y la respuesta elegida, y hace cambios excesivos en el número máximo de bits que se pueden desplazar. [Parece una forma extraña de hacer negocios; Probablemente habría arreglado una excepción en un lenguaje que los tenga. Sin embargo, está claramente definido, que es más importante que exactamente cuál es la definición.] La coerción a 64 bits no ocurre mientras se evalúa la expresión; ocurre cuando la expresión está completa y la asignación sucede.

La referencia a 5 bits es ... intrigante. Significa que si cambia a la izquierda, digamos, 48 ​​o binario 110000, es lo mismo que girar a la izquierda por 16. O, como alternativa, 'x << n' es lo mismo que 'x << (n % 32)'.

+1

D'oh, tienes razón, borró mi respuesta y modificó la tuya :) –

+1

La primera parte de tu respuesta es incorrecta. En Jave, b << 32 es b, no cero. El segundo paragraåh es correcto, sin embargo. –

+1

Corrección: en C el comportamiento está _undefinido_ al cambiar un valor con argumento fuera del rango [0, typewidth - 1]. Por ejemplo, los compiladores opencl de nvidia e intel me dan un comportamiento diferente para la expresión 'b >> 32'. – notso

Cuestiones relacionadas