Страницы

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

понедельник, 2 марта 2020 г.

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

#java #c_sharp #битовые_операции


Есть строка из 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.

Подскажите, в чём соль между этими языками и как решить такую проблему.
    


Ответы

Ответ 1



В этой строке 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;

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

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