¿Por qué la máscara Java cambia los operandos con 0x1F?
En Java:
(0xFFFFFFFF << 1) = 0xFFFFFFFE = 0b1111111111111110
: : :
(0xFFFFFFFF << 30) = 0xE0000000 = 0b1110000000000000
(0xFFFFFFFF << 30) = 0xC0000000 = 0b1100000000000000
(0xFFFFFFFF << 31) = 0x80000000 = 0b1000000000000000
Sin embargo:
(0xFFFFFFFF << 32) = 0xFFFFFFFF = 0b1111111111111111
Lógicamente, esto no tiene sentido, pero lo que creo que está sucediendo es que Java realice una operación similar a:
a << (b % Integer.SIZE)
[editar, al parecer:]a << (b & 0x1F)
Esto aplica a>>
y>>>
, también.
Obviamente, desplazando en> = 32 (en el caso de un Integer) elimina todos los datos del tipo de datos, pero hay ocasiones en que esto es útil. Por ejemplo:
int value = 0x3F43F466; // any value
int shift = 17; // any value >= 0
int carry = value & (-1 << (Integer.SIZE - shift));
if (carry > 0)
; // code...
Por supuesto, esto puede solucionarse, pero encontrar estos errores puede llevar bastante tiempo (solo pasé horas rastreando uno similar). Entonces, mi pregunta:¿Hay alguna razón para no devolver el valor lógico? cuando se desplaza todos los bits hacia fuera?
ACTUALIZAR:Intenté esto en C99, usando lo siguiente:
#include<stdio.h>
main()
{
int i, val;
for (i = 0; i <=36; i++) {
val = (-1 << i);
printf("%d :\t%d\n", i, val);
}
}
Encontré que se comporta igual que Java, enmascarando.i & 0x1F
, mientras que proporciona una advertencia en la compilación cuando se le da un valor constante:
warning: left shift count >= width of type