Страницы

Поиск по вопросам

понедельник, 20 мая 2019 г.

Signed Int32 из двух байт

Есть строка из Java приложения, которая формирует signed INT из двух байт массива:
final int size = array[0] & 0x00FF | array[1] << 8;
где, array[0] равно 0x08, array[1] равно 0xEE. Этот код формирует число -4600
Но C# формирует совсем иное число из аналогичного кода:
int size = array[0] & 0x00FF | array[1] << 8;
Но этот код формирует число 60936
Подскажите, в чём соль между этими языками и как решить такую проблему.


Ответ

В этой строке
final int size = array[0] & 0x00FF | array[1] << 8;
значение выражения записывается в int (4 байта). Это значит, что все операнды преобразовываются в четырехбайтовые значения.
Расширение разрядности в Java происходит путем копирования старшего бита в исходном числе на расширяемые биты.
Итого у Вас было
final int size = 0x08 & 0x00FF | 0xEE << 8;
или в двоичном виде
final int size = 0000_1000b & 0000_0000_0000_0000_0000_0000_1111_1111b | 1110_1110b << 8;
теперь, что получается при расширении
final int size = 0000_0000_0000_0000_0000_0000_0000_1000b & 0000_0000_0000_0000_0000_0000_1111_1111b | 1111_1111_1111_1111_1111_1111_1110_1110b << 8;
В c# такого копирования старшего бита не происходит. (скорее всего там приводится к типу не операнды, а итоговый результат)
Если Вы хотите на Java избежать такого расширения, то применяйте к каждой байтовой переменной операцию побитового И с 0xFF
final int size = array[0] & 0xFF | (array[1] & 0xFF) << 8;
тогда при расширении получится
final int size = 0000_0000_0000_0000_0000_0000_0000_1000b & 0000_0000_0000_0000_0000_0000_1111_1111b | ( 1111_1111_1111_1111_1111_1111_1110_1110b & 0000_0000_0000_0000_0000_0000_1111_1111b ) << 8; final int size = 0000_0000_0000_0000_0000_0000_0000_1000b | 0000_0000_0000_0000_0000_0000_1110_1110b << 8;

Комментариев нет:

Отправить комментарий