Findbugs, предупреждающий: Целочисленный сдвиг на 32 — что это означает?

Становится немного длиннее, но вот тот, который сочетает в себе рекурсивность решения Гарретта с npe-безопасностью исходного вопроса.

def deleteFile(path: String) = {
  val penultimateFile = new File(path.split('/').take(2).mkString("/"))
  def getFiles(f: File): Set[File] = {
    Option(f.listFiles)
      .map(a => a.toSet)
      .getOrElse(Set.empty)
  }
  def getRecursively(f: File): Set[File] = {
    val files = getFiles(f)
    val subDirectories = files.filter(path => path.isDirectory)
    subDirectories.flatMap(getRecursively) ++ files + penultimateFile
  }
  getRecursively(penultimateFile).foreach(file => {
    if (getFiles(file).isEmpty && file.getAbsoluteFile().exists) file.delete
  })
}
10
задан His 21 June 2009 в 07:28
поделиться

2 ответа

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

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

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

long a = b | c;

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

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

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

32
ответ дан 3 December 2019 в 14:06
поделиться

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

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

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

5
ответ дан 3 December 2019 в 14:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: