Anding с 0xff, требуется уточнение - PullRequest
8 голосов
/ 31 марта 2012

В следующем фрагменте рассмотрите возможность замены строки 8 на закомментированный эквивалент

1. private static String ipToText(byte[] ip) {
2.  StringBuffer result = new StringBuffer();
3.
4.  for (int i = 0; i < ip.length; i++) {
5.      if (i > 0)
6.          result.append(".");
7.
8.      result.append(ip[i]); // compare with result.append(0xff & ip[i]);
9.  }
10.
11.     return result.toString();
12. }

.equals(). Тест подтверждает, что добавление 0xff ничего не меняет.Есть ли причина для применения этой маски?

Ответы [ 4 ]

17 голосов
/ 31 марта 2012

byte в Java - это число от −128 до 127 (со знаком, как и любое целое число в Java (за исключением char, если вы хотите его посчитать)).С помощью 0xff вы заставляете его быть положительным int между 0 и 255.

Это работает, потому что Java выполнит расширяющее преобразование в int, используя расширение знака, поэтому вместоотрицательный byte у вас будет отрицательный int.Маскирование с помощью 0xff оставит только младшие 8 битов, что делает число снова положительным (и то, что вы изначально предполагали).

Вы, вероятно, не заметили разницу, потому что вы тестировали с byte[] столько значения меньше 128.

Маленький пример:

public class A {
    public static void main(String[] args) {
        int[] ip = new int[] {192, 168, 101, 23};
        byte[] ipb = new byte[4];
        for (int i =0; i < 4; i++) {
            ipb[i] = (byte)ip[i];
        }

        for (int i =0; i < 4; i++) {
            System.out.println("Byte: " + ipb[i] + ", And: " + (0xff & ipb[i]));
        }
    }
}

Это печатает

Byte: -64, And: 192
Byte: -88, And: 168
Byte: 101, And: 101
Byte: 23, And: 23

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

3 голосов
/ 31 марта 2012

Поскольку вы уже работаете с массивом байтов здесь и выполняете побитовую операцию, вы можете игнорировать то, как Java обрабатывает все байты как подписанные.В конце концов, вы работаете на уровне битов, и на уровне битов нет таких вещей, как «подписанные» или «беззнаковые» значения.

Маскировка 8-битного значения (байт)все 1 - пустая трата циклов, потому что ничто никогда не будет замаскировано.Битовое И вернет бит true, если оба сравниваемых бита верны, поэтому, если маска содержит все 1, то вы гарантированно, что все биты маскируемого значения останутся неизменными после операции AND.

Рассмотрим следующие примеры:

Mask off the upper nibble:
    0110 1010
AND 0000 1111 (0x0F)
  = 0000 1010
Mask off the lower nibble:
    0110 1010
AND 1111 0000 (0xF0)
  = 0110 0000
Mask off... Eh, nothing:
    0110 1010
AND 1111 1111 (0xFF)
  = 0110 1010

Конечно, если бы вы работали здесь с полнофункциональным int, вы бы получили результат, если бы другие сказали:заставить "int быть эквивалентом беззнакового байта.

1 голос
/ 31 марта 2012

Это должно иметь значение только при наличии отрицательных байтов.& 0xff обычно используется для интерпретации байта как беззнакового.

1 голос
/ 31 марта 2012

В этом примере я не вижу, как это будет иметь значение. Вы идете в 0xff с байтом. Байт по определению имеет 8 битов, а сложение маскирует последние 8 битов. Итак, вы берете последние 8 из 8, это ничего не даст.

Инициация с 0xff имела бы смысл, если бы то, что вы делали с ним, было больше байта, короткого или целого числа или чего-то еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...