24 位无符号整数



我开始使用HART(高速公路可寻址远程传感器)协议,我发现了一些东西,让我们说不同,我试图理解它,更准确地说是uint24。我知道这种结构在内部使用 UInt32 进行存储和大多数其他常见的预期整数功能,因此使用 24 位整数不会节省内存。但我的问题是如何将 UInt32 转换为这种特定类型,我在 Javascript 中找到了这些代码行,但我不知道这些左移的目的是什么。

var getUint24 = function(bytes)
{
return (DataView(bytes.buffer).getUint16(0) << 8) + DataView(bytes.buffer).getUint8(0 + 2);
}

另外,我发现了这个将数字转换为 4 个字节的函数。我也不知道这些移位的目的是什么,但也许如果我理解这些,我可以创建我自己的函数版本,将一个简单的数字 ex: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 & 0xff000000) >> 24,
(num & 0x00ff0000) >> 16,
(num & 0x0000ff00) >> 8,
(num & 0x000000ff)
];
return arr;
}

如果有人能帮助我理解那些转移的倾注,我将不胜感激,C/C++版本也非常受欢迎。

简答

  • 左移<<是用零填充有效位,以便将来连接成单个值;
  • 右移>>是将值的段提取为较小数据类型的一部分(在应用掩码之后);

抽象

Shift & 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, 1111, 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并希望获得第二位的值,我们需要应用 &-mask,其中根据1评估的主题位保持原始值,而根据0评估的其余位将任何值转换为0

masked    = 011 & 010    # 010
bit_value = masked >> 1  # 001

就像我们的ABCDEF12一样

x = 0xABCDEF12 & 0xFF000000   # x = 0xAB000000
x >> 24                       # x = 0x000000AB
...

这样我们将得到数组[0xAB, 0xCD, 0xEF, 0x12]。在没有移动的情况下,我们得到了阵列[0xAB000000, 0x00CD0000, 0x0000EF00, 0x00000012]这不是我们想要的。

最新更新