Битовый сдвиг в Java - PullRequest
       17

Битовый сдвиг в Java

0 голосов
/ 22 сентября 2011

Может быть, я слишком устал.
Почему следующие значения не отображаются одинаково?

int x = 42405;
System.out.println(x << 8);  
System.out.println((x &0x00ff) << 8);  

Младшие биты должны быть чистыми в обоих случаях

Ответы [ 2 ]

5 голосов
/ 22 сентября 2011

РЕДАКТИРОВАТЬ: Хорошо, я оставляю нижнюю часть для потомков ...

Если x равен int, то это довольно просто: x << 8 будет иметь то же значение, что и x & 0xff тогда и только тогда, когда ни один из «средних» 16 битов не установлен:

  • Старшие 8 бит x будут считаться неактуальными с помощью левого сдвига
  • Нижние 8биты x сохраняются с помощью маскировки

Если имеется любой из набора "средних" 16 битов, то x & 0xff будет отличаться от x вбит, который все еще сохраняется при сдвиге, поэтому результаты будут другими.

Я не понимаю, почему вы ожидаете, что они всегда будут давать одинаковые результаты ...


Я собираюсь предположить, что тип x равен byte, и что он на самом деле отрицательный.

Операция сдвига не определена для byte, поэтому сначала выполняется преобразование в int... и это может измениться в зависимости от того, есть ли у вас маска.

Итак, давайте рассмотрим случай, когда x равно -1.Тогда (int) x равно также -1 - т.е. битовая комбинация равна 1 с.Сдвиньте влево на 8 бит, и вы получите битовую комбинацию 24 1 с, за которой следуют 8 0:

11111111111111111111111100000000 = -256

Теперь рассмотрим вторую строку кода - для этого требуется x & 0xff, который будет принимать тольконижние 8 битов повышенного значения x - то есть 255. Вы сдвигаете влево на 8 битов, и в итоге получается 16 0 с, 8 1 с, затем 8 0:

00000000000000001111111100000000 = 65280
4 голосов
/ 22 сентября 2011

Ниже x равен> 0xff, и в одном случае вы маскируете верхние 3 байта, что означает, что вы делаете (0x123 & 0x00ff) << 8, что будет 0x23 << 8 И это весьма отличается от 0x123 << 8

int x = 0x123;
System.out.println(x << 8);  //prints 74496
System.out.println((x &0x00ff) << 8); //prints 8960

И если x является байтом, он будет «повышен» до int перед сдвигом, а если он отрицательный, он будет подписывать расширение, и вы получите целую партию из 1 бита, установленную в целое число, котороев одном случае маскируется с & 0xff, а в другом не маскируется

, т. е.

byte x = (byte)0xAA; //x is negative
System.out.println(x << 8);  //prints -22016
System.out.println((x &0x00ff) << 8); //prints 43520
...