Что делает value & 0xff в Java?

101

У меня есть следующий код Java:

byte value = 0xfe; // corresponds to -2 (signed) and 254 (unsigned)
int result = value & 0xff;

Результат - 254 при печати, но я понятия не имею, как работает этот код. Если &оператор просто побитовый, то почему он не дает байта, а целого числа?

Dagronlund
источник
Копирую код в Eclipse. Он предупреждает меня: «Несоответствие типов: невозможно преобразовать из int в байт». Если оно изменится на int value = 0xfe;
Бен Ченг
1
@BenCheng должен бытьbyte value = (byte) 0xfe;
Бек

Ответы:

173

Он устанавливает result(беззнаковое) значение, полученное в результате помещения 8 бит valueв младшие 8 бит result.

Причина, по которой что-то подобное необходимо, заключается в том, что byteэто подписанный тип в Java. Если вы только что написали:

int result = value;

то resultбудет в конечном итоге со значением ff ff ff feвместо 00 00 00 fe. Еще одна тонкость заключается в том, что &определяется для работы только со intзначениями 1 , поэтому происходит следующее:

  1. valueповышается до int( ff ff ff fe).
  2. 0xffявляется intбуквальным ( 00 00 00 ff).
  3. &Наносится с получением желаемого значения для result.

(Дело в том, что преобразование в intпроисходит до применения &оператора.)

+1 Ну не совсем так. &Оператор работает на longзначениях , а также, если один из операндов является long. Но не дальше byte. См. Спецификацию языка Java, разделы 15.22.1 и 5.6.2 .

Тед Хопп
источник
Что означает x в этой записи? x не является числом или шестнадцатеричным числом?
Callat
3
@KazRodgers - префикс 0x(или 0X) сообщает Java, что следующий за ним целочисленный литерал следует интерпретировать как шестнадцатеричный (основание 16). Java также поддерживает пустой 0префикс для восьмеричных литералов и префикс 0b(или 0B) для двоичных литералов. См. Спецификацию языка Java для получения дополнительной информации о целочисленных литералах.
Тед Хопп
Что следует за буквальным? Так, например, если бы у меня был 0x3fa. 3fa - это часть, переводимая в буквальное число, а 0x означает, что "это шестнадцатеричное число"? @TedHopp?
Callat
1
@KazRodgers - Совершенно верно. Обратите внимание, что 0xили 0bсамо по себе (без каких-либо цифр) является недопустимым синтаксисом в Java.
Тед Хопп
1
@DmitryMinkovsky - Шестнадцатеричный битовый шаблон feв 8 битах, дополнение до двух соответствует десятичному значению −2. Чтобы сохранить значение, Integer.valueOf(byte)необходимо произвести ff ff ff fe(−2 в 32-битном формате, дополнение до двух), а не 00 00 00 fe(десятичное значение 254). Это преобразование (от byteзначения feк intзначению ff ff ff fe) известно как расширение знака и является частью спецификации языка Java. Цель value & 0xffсостоит в том, чтобы отменить расширение знака (т. Е. Имитировать нулевое расширение, чего нет в Java).
Тед Хопп
57

Из http://www.coderanch.com/t/236675/java-programmer-SCJP/certification/xff

Шестнадцатеричный литерал 0xFF равен int (255). Java представляет int как 32 бита. В двоичном формате это выглядит так:

00000000 00000000 00000000 11111111

Когда вы делаете немного мудрое И с этим значением (255) для любого числа, он будет замаскировать (сделать НУЛИ) все, кроме самых младших 8 бит числа (будет как есть).

... 01100100 00000101 & ...00000000 11111111 = 00000000 00000101

& - это что-то вроде%, но не совсем .

А почему 0xff? это в ((степень 2) - 1). Все ((степень 2) - 1) (например, 7, 255 ...) будут вести себя примерно как оператор%.

Тогда
в двоичном формате 0 - это все нули, а 255 выглядит так:

00000000 00000000 00000000 11111111

И -1 выглядит так

11111111 11111111 11111111 11111111

Когда вы выполняете побитовое И для 0xFF и любого значения от 0 до 255, результат будет таким же, как и значение. И если какое-либо значение больше 255, результат будет в пределах 0-255.

Однако если вы это сделаете:

-1 & 0xFF

ты получаешь

00000000 00000000 00000000 11111111, что НЕ равно исходному значению -1 ( 11111111255 в десятичной системе).


Еще несколько манипуляций с битами: (Не относится к вопросу)

X >> 1 = X/2
X << 1 = 2X

Проверьте, установлен ли какой-либо конкретный бит (1) или нет (0), затем

 int thirdBitTobeChecked =   1 << 2   (...0000100)
 int onWhichThisHasTobeTested = 5     (.......101)

 int isBitSet = onWhichThisHasTobeTested  & thirdBitTobeChecked;
 if(isBitSet > 0) {
  //Third Bit is set to 1 
 } 

Установить (1) конкретный бит

 int thirdBitTobeSet =   1 << 2    (...0000100)
 int onWhichThisHasTobeSet = 2     (.......010)
 onWhichThisHasTobeSet |= thirdBitTobeSet;

ReSet (0) конкретный бит

int thirdBitTobeReSet =   ~(1 << 2)  ; //(...1111011)
int onWhichThisHasTobeReSet = 6      ;//(.....000110)
onWhichThisHasTobeReSet &= thirdBitTobeReSet;

XOR

Просто обратите внимание, что если вы выполните операцию XOR дважды, получится то же значение.

byte toBeEncrypted = 0010 0110
byte salt          = 0100 1011

byte encryptedVal  =  toBeEncrypted ^ salt == 0110 1101
byte decryptedVal  =  encryptedVal  ^ salt == 0010 0110 == toBeEncrypted :)

Еще одна логика с XOR:

if     A (XOR) B == C (salt)
then   C (XOR) B == A
       C (XOR) A == B

Вышеизложенное полезно для замены двух переменных без температуры, как показано ниже.

a = a ^ b; b = a ^ b; a = a ^ b;

ИЛИ

a ^= b ^= a ^= b;
Канагавелу Сугумар
источник
Также посмотрите @ Битовые манипуляции stackoverflow.com/questions/13422259/…
Канагавелу Сугумар
5

Это помогает сократить количество кодов. Иногда он используется в значениях RGB, состоящих из 8 бит.

где 0xff означает 24 (0) и 8 (1), например00000000 00000000 00000000 11111111

Он эффективно маскирует переменную, поэтому оставляет только значение в последних 8 битах и ​​игнорирует все остальные биты.

Это чаще всего наблюдается в случаях, например, при попытке преобразовать значения цвета из специального формата в стандартные значения RGB (длина которых составляет 8 бит).

Отличное объяснение см. Здесь

AndroidGeek
источник
0

В 32 битном формате системы шестнадцатеричное значение 0xffпредставляет 00000000000000000000000011111111то есть 255(15*16^1+15*16^0)в десятичной системе . а побитовый оператор & маскирует те же самые 8 правых битов, что и в первом операнде.

Маниш Кумар
источник
не могли бы вы объяснить немного больше.
ashishdhiman2007