Dlaczego operacja przesunięcia maski Java z 0x1F?
W Javie:
(0xFFFFFFFF << 1) = 0xFFFFFFFE = 0b1111111111111110
: : :
(0xFFFFFFFF << 30) = 0xE0000000 = 0b1110000000000000
(0xFFFFFFFF << 30) = 0xC0000000 = 0b1100000000000000
(0xFFFFFFFF << 31) = 0x80000000 = 0b1000000000000000
Jednak:
(0xFFFFFFFF << 32) = 0xFFFFFFFF = 0b1111111111111111
Logicznie nie ma to sensu, ale uważam, że dzieje się tak, że Java wykonuje operację podobną do:
a << (b % Integer.SIZE)
[edytuj, najwyraźniej:]a << (b & 0x1F)
Dotyczy to>>
i>>>
, zbyt.
Oczywiście przesunięcie o> = 32 (w przypadku liczby całkowitej) usuwa wszystkie dane z typu danych, ale są chwile, kiedy jest to przydatne. Na przykład:
int value = 0x3F43F466; // any value
int shift = 17; // any value >= 0
int carry = value & (-1 << (Integer.SIZE - shift));
if (carry > 0)
; // code...
Oczywiście można to naprawić, ale znalezienie tych błędów może być dość czasochłonne (spędziłem godziny na śledzeniu podobnego). Moje pytanie:Czy istnieje powód, aby nie zwracać wartości logicznej kiedy przesuwasz wszystkie bity?
AKTUALIZACJA:Próbowałem tego w C99, korzystając z następujących:
#include<stdio.h>
main()
{
int i, val;
for (i = 0; i <=36; i++) {
val = (-1 << i);
printf("%d :\t%d\n", i, val);
}
}
Odkryłem, że zachowuje się tak samo jak Java, maskowaniei & 0x1F
, podczas gdy zapewnia ostrzeżenie przy kompilacji, gdy otrzyma stałą wartość:
warning: left shift count >= width of type