Каков наилучший способ обойти тот факт, что все байты Java подписаны?

В Java нет такой вещи как неподписанный байт.

Работая с некоторым кодом низкого уровня, иногда вам нужно работать с байтами, у которых значения без знака больше 128, что заставляет Java интерпретировать их как отрицательное число из-за того, что MSB используется для знака.

Какой хороший способ обойти это? (Сказать не использовать Java не вариант)

14.08.2008 14:14:03
7 ОТВЕТОВ
РЕШЕНИЕ

При чтении любого отдельного значения из массива скопируйте его в что-то вроде short или целого числа и вручную конвертируйте отрицательное число в положительное значение, которое должно быть.

byte[] foobar = ..;
int value = foobar[10];
if (value < 0) value += 256 // Patch up the 'falsely' negative value

Вы можете сделать аналогичное преобразование при записи в массив.

20
14.08.2008 14:24:50
Намного проще и эффективнее сделать int value = (foobar [10] & 0xFF);
Lawrence Dol 2.05.2009 07:33:43
Возможно, но я хотел, чтобы мой код был максимально понятным и поучительным. Кроме того, я не знаю, что '&' делает для отрицательных целых чисел в Java (по крайней мере, не без поиска в Google), поэтому я проигнорировал это.
pauldoo 4.05.2009 10:47:50
почему бы и сделать что-то другое для отрицательных чисел. И это логическая операция, она работает с отдельными битами, она знает, проверяет или заботится, является ли число положительным, отрицательным или любым другим значением.
mP. 16.06.2011 02:53:47
Я подумал, что, возможно, 0xFF будет обрабатываться как байт со знаком (который будет равен -1), а затем расширенный знак до 32-разрядного целого числа со знаком (который даст 0xFFFFFFFF aka -1) перед передачей в качестве аргумента '&'. Это дало бы неправильный результат. Из обсуждения ясно, что Java не сделает этого, но я подумал, что лучше не рисковать.
pauldoo 5.07.2011 16:48:03

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

-1
14.08.2008 14:17:48

Вероятно, вам лучше всего использовать целое число, а не байт. В нем есть место для чисел, превышающих 128, без необходимости создавать специальный объект для замены байта.

Это также предлагают люди умнее меня (всех)

0
14.08.2008 14:22:24

Лучший способ сделать биты манипуляции / неподписанные байты - использовать int s. Несмотря на то, что они подписаны, у них есть много свободных битов (всего 32), которые можно рассматривать как неподписанный байт. Кроме того, все математические операторы преобразуют меньшие числа с фиксированной точностью в int . Пример:

short a = 1s;
short b = 2s;
int c = a + b; // the result is up-converted
short small = (short)c; // must cast to get it back to short

Из-за этого лучше всего придерживаться целого числа и маскировать его, чтобы получить интересующие вас биты. Пример:

int a = 32;
int b = 128;
int foo = (a + b) | 255;

Вот еще немного информации о примитивных типах Java: http://mindprod.com/jgloss/primitive.html

Последнее тривиальное примечание: в Java есть одно число без знака с фиксированной точностью. Это символ примитива.

0
19.08.2008 03:39:43

Использование ints обычно лучше, чем использование шорт, потому что в любом случае java использует 32-битные значения внутри себя (даже для байтов, если не в массиве), поэтому использование ints позволит избежать ненужного преобразования в / из коротких значений в байт-коде.

1
19.08.2008 08:03:27
Что ж, если значение всегда будет байтом (то есть 8 бит), тогда использование byteболее понятно и лучше передает смысл кода, поэтому я бы использовал его для удобства чтения, даже если он использует то же пространство, что и int.
sleske 17.01.2011 00:54:36
Это очень верно, хотя вы получаете дополнительный байт-код, чтобы привести значения в байты и обратно, так что есть небольшие накладные расходы. Читаемость> крошечные нематериальные выгоды, хотя.
izb 17.01.2011 08:51:00
Кроме того, понимание того, что это intлучше byteподходит для ваших целей, не поможет, если вам случится положиться на библиотеку, которая где- то использует (на ум приходит USB-стек на Android).
user149408 20.05.2017 22:50:19

На самом деле можно избавиться от оператора if и дополнения, если вы сделаете это следующим образом.

byte[] foobar = ..;
int value = (foobar[10] & 0xff);

Таким образом, Java не интерпретирует байт как отрицательное число и также переворачивает бит знака на целое число.

79
1.08.2018 16:00:06
Небольшое замечание по эффективности: при компиляции выражения, подобного приведенному выше, в нативные машинные инструкции, клиентская виртуальная машина Java Hotspot выполнит обычное продвижение байта к int (с расширением знака ), за которым следует операция AND. Виртуальная машина Hotspot Server достаточно сообразительна, чтобы выполнить продвижение с нулевым расширением, пропуская AND.
Boann 8.02.2013 14:56:44

Я знаю, что это очень поздний ответ, но я наткнулся на эту тему, пытаясь сделать то же самое. Проблема заключается в том, чтобы просто определить, является ли байт Java> 127.

Простое решение:

if((val & (byte)0x80) != 0) { ... }

Если реальная проблема составляет> 128, просто добавьте еще одно условие к этому оператору if.

0
18.02.2011 23:33:42