В Java:
(0xFFFFFFFF << 1) = 0xFFFFFFFE = 0b1111111111111110
: : :
(0xFFFFFFFF << 30) = 0xE0000000 = 0b1110000000000000
(0xFFFFFFFF << 30) = 0xC0000000 = 0b1100000000000000
(0xFFFFFFFF << 31) = 0x80000000 = 0b1000000000000000
Однако:
(0xFFFFFFFF << 32) = 0xFFFFFFFF = 0b1111111111111111
Логически это не имеет никакого смысла, но, по моему мнению, это Java, выполняющая операцию, похожую на:
a << (b % Integer.SIZE)
[edit, по-видимому:] a << (b & 0x1F)
Это относится и к >>
и >>>
.
Очевидно, что сдвиг по >= 32 (в случае Integer) удаляет все данные из типа данных, но есть моменты, когда это полезно. Например:
int value = 0x3F43F466; // any value
int shift = 17; // any value >= 0
int carry = value & (-1 << (Integer.SIZE - shift));
if (carry > 0)
; // code...
Конечно, это может быть исправлено, но найти эти ошибки можно довольно много (я просто потратил часы, отслеживая аналогичный вариант). Итак, мой вопрос: Есть ли причина для отказа от логического значения при смещении всех битов?
UPDATE:
Я попробовал это на C99, используя следующее:
#include<stdio.h>
main()
{
int i, val;
for (i = 0; i <=36; i++) {
val = (-1 << i);
printf("%d :\t%d\n", i, val);
}
}
Я обнаружил, что он ведет себя так же, как Java, маскируя i & 0x1F
, тогда как он дает предупреждение при компиляции при заданном постоянном значении:
warning: left shift count >= width of type