Побитовое-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 теперь удалены.