#javascript #c #c #byte #bit-shift
#javascript #c #c #байт #битовый сдвиг
Вопрос:
Я начинаю работать с HART (адресуемый по шоссе удаленный преобразователь) Протокол и я нашли что-то, скажем, другое, и я пытаюсь это понять, точнее, uint24. Я понимаю, что эта структура использует UInt32 внутри для хранения и большинства других общих ожидаемых функций целых чисел, поэтому использование 24-битного целого числа не сэкономит память. Но мой вопрос в том, как я могу преобразовать UInt32 в этот конкретный тип, я нашел эти строки кода в Javascript, но я не знаю, какова цель этого сдвига влево.
var getUint24 = function(bytes)
{
return (DataView(bytes.buffer).getUint16(0) << 8) DataView(bytes.buffer).getUint8(0 2);
}
Кроме того, я нашел эту функцию, которая преобразует число в 4 байта. Я также не знаю, какова цель этих сдвигов, но, возможно, если я пойму это, я смогу создать свою собственную версию функции, которая преобразует простое число, например: 4, в его версию uint24.
/**
*
* @function ToBytesInt32 "Convert number to 4 bytes (eg: ToBytesInt32(2) returns 00 00 00 02"
* @param {number} num The input value
* @return {byte array}
*/
function ToBytesInt32BigEndian(num) {
if (isNaN(num)) {
throw "ToBytesInt32 received Nan! Called from: "
testUtils.StrReplace.caller.toString().split('n')[0];
}
arr = [
(num amp; 0xff000000) >> 24,
(num amp; 0x00ff0000) >> 16,
(num amp; 0x0000ff00) >> 8,
(num amp; 0x000000ff)
];
return arr;
}
Если кто-нибудь может помочь мне понять суть этих изменений, я бы оценил это, также очень приветствуется версия C / C .
Комментарии:
1. Обычно целое число без знака хранится в памяти в виде его шестнадцатеричного представления (сильно отличается для других типов). Сдвиг влево / вправо просто «перемещает» некоторые позиции байтов влево / вправо, заполняя новые дыры нулями и теряя перемещенные байты. Перемещение в крайнюю правую позицию дает вам уникальный байт. Маски, используемые с
amp;
, просто выбирают некоторые позиции, а остальные равняют нулю.
Ответ №1:
Короткий ответ
<<
сдвиг влево — это дополнение значащих битов нулями для последующего объединения в одно значение;>>
сдвиг вправо является частью извлечения сегмента значения в меньший тип данных (выполняется после применения маски);
Аннотация
Shift amp; sum — это способ упаковки / распаковки значений, когда кадр чтения / записи меньше длины значения. Допустим, у нас есть 4-битное значение: 1011
. И мы можем прочитать его только по 2-битным кадрам : [10], [11]
.
Давайте предположим, что мы читаем поток слева направо.
# offset 0 bits
a = stream(0) # a = 10
a << 2 # a = 1000
b = stream (2) # b = 11
return a b # 1000 11 = 1011
Также вам следует обратить внимание на BE/LE (большой / Маленький порядковый номер). В разных порядковых числах значение 1011
может быть представлено в потоке как 10, 11
или 11, 10
.
Пример getUint24
В случае getUint24
примера у нас есть 24-битное значение, упакованное в виде последовательности [16 bit, 8 bit]
. Давайте нарисуем его так [XY, Z]
, где одна буква равна 1 байту.
# offset 0 bytes
a = DataView(bytes.buffer).getUint16(0) # a = XY
a << 8 # a = XY0
# offset 2 bytes
b = DataView(bytes.buffer).getUint8(2) # b = Z
return a b # XY0 Z = XYZ
И снова bytes.buffer
может сохранять значение либо как [XY, Z]
, либо [Z, XY]
. getUintX(offset)
Скрывает от нас эту информацию. Но если вы хотите написать собственный конвертер, вам нужно выяснить, какой формат используется в вашем случае.
ToBytesInt32BigEndian пример
Здесь мы видим еще одну проблему упаковки значений — применение маски.
Допустим, у нас есть 32-битное значение AB CD EF 12
. Мы можем применить маску для извлечения необходимого сегмента значения.
Например, если у нас есть 3-битное значение 011
, и мы хотели бы получить значение второго бита, нам нужно применить amp;-mask, где подлежащие биты, вычисленные по отношению 1
к исходному значению, сохраняют исходное значение, в то время как остальные биты, вычисленные против 0
, превращают любое значение в 0
.
masked = 011 amp; 010 # 010
bit_value = masked >> 1 # 001
Таким же образом с нашим ABCDEF12
x = 0xABCDEF12 amp; 0xFF000000 # x = 0xAB000000
x >> 24 # x = 0x000000AB
...
Таким образом, мы получим массив [0xAB, 0xCD, 0xEF, 0x12]
. Без сдвига мы получили массив [0xAB000000, 0x00CD0000, 0x0000EF00, 0x00000012]
, который не является тем, что мы хотим.