2009-06-21 5 views
8

я сканировал исходный третий участник код с помощью FindBugs (просто быть осторожным, прежде чем интегрироваться в него шахты), и обнаружили следующее предупреждение:Предупреждение Findbugs: целочисленный сдвиг на 32 - что это значит?

long a = b << 32 | c 

Ошибка: Integer сдвиг на 32 Шаблон ID: ICAST_BAD_SHIFT_AMOUNT , тип: BSHIFT, категории: КОРРЕКТНОСТЬ

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

Не могли бы вы объяснить, что именно означает это выше?

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

ответ

30

От Java Language Specification:

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

Так что, если б это ИНТ, выражение идентично

long a = b | c; 

, который я очень сомневаюсь, что это предназначено. Это, вероятно, было

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

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

+0

Итак,' int >> 32 (0x100000) == int >> 0 (0x00000) '? –

+1

Странный псевдосинтакс, который вы используете, но да, вот и все. – UndefinedBehavior

5

Отредактировано: Проблема почти наверняка связано с тем, что «Ь» является «INT», а не «долго».

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

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

+1

D'oh, вы правы, удалили мой ответ и переделали ваш :) –

+1

В первой части вашего ответа неверно. В Jave b << 32 - b, а не ноль. Однако второй параграф является правильным. –

+1

Коррекция: в поведении C _undefined_ при смещении значения с аргументом вне диапазона [0, typewidth - 1]. Например, opencl-компиляторы из nvidia и intel дают мне другое поведение для выражения «b >> 32». – notso