Предупреждение об ошибках:Целочисленный сдвиг на 32 — что это значит?

StackOverflow https://stackoverflow.com/questions/1023373

  •  06-07-2019
  •  | 
  •  

Вопрос

Я сканировал сторонний исходный код с помощью Findbugs (просто на всякий случай перед интеграцией в него своего) и обнаружил следующее предупреждение:

long a = b << 32 | c

Ошибка:Целочисленный сдвиг на 32 Идентификатор шаблона:ICAST_BAD_SHIFT_AMOUNT, введите:BSHIFT, категория:ПРАВИЛЬНОСТЬ

Код выполняет целочисленный сдвиг постоянное количество за пределами диапазона 0..31.Результатом этого является использование нижних 5 битов целого значения чтобы решить, сколько переключиться.Это вероятно, не хочу ожидалось, и это по крайней мере запутанно.

Кто-нибудь может объяснить, что именно означает вышесказанное?

Спасибо!(Я новичок в программировании на Java)

Это было полезно?

Решение

Из Спецификация языка Java:

Если расширенный тип левого операнда — int, в качестве расстояния сдвига используются только пять младших битов правого операнда.Это как если бы правый операнд был подвергнут побитовому логическому оператору И & (§15.22.1) со значением маски 0x1f.Таким образом, фактически используемый диапазон переключения всегда находится в диапазоне от 0 до 31 включительно.

Таким образом, если b является целым числом, выражение идентично

long a = b | c;

я очень сомневаюсь, что это то, что задумано.Вероятно, это должно было быть

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

(Если b уже длинное, код правильный и FindBugs ошибается в отношении ошибки).

Другие советы

Отредактировано: Проблема почти наверняка связана с тем, что «b» — это «int», а не «long».

В C, если «b» — целое число, а не длинное, и вы сдвигаете влево на 32 бита, все биты исходного значения были удалены, поэтому результат общего выражения будет таким же, как 'c' вы бы вызвали неопределенное поведение, поэтому допустим любой результат.Java определяет вещи по-другому — как отмечено в комментарии Расмуса Фабера и выбранном ответе — и выполняет слишком длинные сдвиги по модулю максимального количества бит, которые можно сдвинуть.[Это кажется странным способом ведения бизнеса;Я бы, наверное, устроил исключение для языка, в котором они есть.Однако оно четко определено, что более важно, чем само определение.] Приведение к 64-битному формату не происходит во время вычисления выражения;это происходит, когда выражение завершено и происходит присвоение.

Ссылка на 5 бит...интригующе.Это означает, что если вы сдвинете влево, скажем, на 48 или двоичное 110 000, это будет то же самое, что сдвиг влево на 16.Или, альтернативно, 'x << n' такой же как 'x << (n % 32)'.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top