通过位地址从存储器中提取字节

时间:2014-10-28 12:32:56

标签: c++

我正在处理其值中具有各种奇怪位数的数据(例如3位或71位,您可以想象的任何东西),所有数据都紧密地序列化在一起。为了提取数据,我想我首先要创建一个能够逐位检索的函数,然后我可以将这些函数绑定在一起超过8位。

现在我感到非常困惑,这是我与之合作的内容:

unsigned char Data[] = { 0, 255, 2, 255, 4, 5, 6, 7 };
UInt64 BitLen = 64; //test data
UInt64 ByteLen = BitLen % 8 == 0 ? BitLen / 8 : BitLen / 8 + 1;

....

unsigned char GetUChar(UInt64 BitIdx) {
    UInt64 ByteIdx = BitIdx / 8;
    UInt16 Bulk = ByteLen - 1 == ByteIdx ? Data[ByteIdx] : *(UInt16*)&Data[ByteIdx];
    return Bulk >> (8 - (BitIdx - ByteIdx)) % 8;
}

这个想法是,如果包含BitIdx的字节是数据集中的最后一个,则将值检索为char,否则检索为UInt16(应该获取该字节和下一个字节)。 然后

BitOffset = BitIdx - ByteIdx * 8

8 - BitOffset =从左边填充多少

最后

和%8,这样如果BitIdx与ByteIdx对齐,则移位量= 0.

然后我将它移到右边并返回低位字节。

所以为了测试,我使用在线十进制到二进制转换器来找出二进制的测试数据是

00000111 00000110 00000101 00000100 11111111 00000010 11111111 00000000

我使用该函数从BitIdx 14开始查找char,结果为10111111,而需要10000001

有一段时间我认为这些位是倒退然后是字节但是没有任何意义了。有没有更简单的方法从字节数组中从位地址Y开始提取X位数?

2 个答案:

答案 0 :(得分:0)

您忘记将ByteIdx乘以8,然后再从BitIdx中减去它:

return Bulk >> ((8 - (BitIdx - 8*ByteIdx)) % 8);

注意:使用在分割前添加ByteLen的常见技巧可以简化计算N-1

UInt64 ByteLen = (BitLen + 7) / 8;

答案 1 :(得分:0)

请注意,如果您在小端系统(例如Intel)上运行,那么读取两个字节作为UInt16 将为您提供这些字节&#34;向后&#34;。< / p>

e.g。

char b[] = {1,0};
UInt16 w = *(Uint16*)&b[0];

提供w == 100000000 00000001)而不是25600000001 00000000),如您所料。

相关问题