Побитовое-ANDing с 0xff важно?

Не побитовое-ANDing с 0xff по существу означает получение того же значения обратно, если на то пошло, в этом коде?

byte[] packet = reader.readPacket();
short sh;
sh = packet[1];
sh &= 0xFF;
System.out.print(sh+" ");

Как ни странно, я получаю -1, если этот ANDing не включен, а 255, если он включен. Может ли кто-нибудь объяснить причину?

Как я вижу, 0xff - это всего 1111 1111. Не правда ли?

Ответ 1

Да, 0xff - это просто 1111 1111. Но это попытка отобразить значение без знакового байта, даже если в Java byte подписаны. Значение 0xff составляет -1 для подписанного byte, но оно 255 в short.

Когда будет прочитано значение byte 0xff, печать значения даст -1. Поэтому он присваивается short, который имеет больший диапазон и может хранить значения byte, которые обычно переполняются как отрицательное число, как byte как положительное целое число, например. 144 как byte есть 0x90, или -112, но он может быть правильно сохранен как 144 как short.

Поэтому значение byte -1 присваивается значению short. Но что это делает? Происходит примитивное расширение конверсии, а отрицательные значения расширены. Итак, 1111 1111 становится 11111111 11111111, еще -1, но на этот раз как short.

Затем битмаска 0xff (00000000 11111111) используется для вывода последних 8 бит:

  -1: 11111111 1111111
0xFF: 00000000 1111111
======================
 255: 00000000 1111111

Это просто способ получить значение unsigned byte, преобразовывая его в short, а затем маскируя исходные биты из byte, чтобы отобразить его как значение без знака.

Ответ 2

A byte имеет диапазон от -128 до 127. Это означает, что некоторые значения отрицательны. Это все значения, в которых установлен верхний бит. Итак, (byte) 0xFF равно -1. Когда вы используете расширение знака, чтобы сделать его подписанным, оно становится (short) 0xFFFF, которое равно -1 как короткое. Когда вы маскируете его, он прерывает расширенные биты, и вы обрабатываете байт, как если бы он был без знака.


Вы не получите -1, если ваш код не отличается от того, что у вас есть в вопросе.

for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) {
    short s = b;
    s &= 0xff;
    System.out.println(b + " & 0xFF = " + s);
}

печатает

-128 & 0xFF = 128
-127 & 0xFF = 129
....
-2 & 0xFF = 254
-1 & 0xFF = 255
0 & 0xFF = 0
1 & 0xFF = 1
...
125 & 0xFF = 125
126 & 0xFF = 126

Ответ 3

(Предположим, что два дополнения повсюду) Две вещи:

  • Байт подписывается, поэтому 0xff в байте равен -1.
  • При переходе от меньшего типа данных к более крупному типу данных (в этом случае от byte до a short) значение сохраняется. Таким образом, sh = packet[1] установил sh в -1, который равен 0xffff.

Вещь с точкой № 2 заключается в том, что "дополнительные" биты заполняются с помощью 1s, чтобы сохранить значение, когда исходное значение отрицательное. Идея ANDing с 0xff заключается в том, что sh теперь содержит 0x00ff, причем эти "лишние" 1 теперь удалены.