Предупреждение Findbugs: целочисленное смещение на 32 - что это значит? - PullRequest
10 голосов
/ 21 июня 2009

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

long a = b << 32 | c

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

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

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

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

Ответы [ 2 ]

32 голосов
/ 21 июня 2009

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

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

Так что, если b - это int, выражение идентично

long a = b | c;

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

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

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

5 голосов
/ 21 июня 2009

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

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

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

...