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

questionAnswers(2)

yourAnswerToTheQuestion