我正在尝试解决一个驱动程序问题,在这个问题中,我必须从任意位置开始的任意比特流中提取一些比特。我在这附近搜索了一下帖子,发现大部分涉及的位操作都是64位机器或没有特殊的存储布局条件。
好吧,位流作为一个字节数组存储在一个32位微处理器中。但是流是小端的,例如下面的字节流
LSBit(位0)-->0100 1001 0100 0100存储在内存中
字节0
1001 0010位布局,位7->1001 0010->位0
字节1
0010 0010位布局,位15->0010 0010->位8
这里一个字节的位布局是Big Endian,但是字节是Little Endian。
如果我必须从小endian流中提取位4到11才能得到00101001,那么我需要提取
从字节0
1001,字节0的高位半字节
从字节1
0010,字节1的下半字节
将位从字节1左移到字节0的0010或1001
问题是流的长度可以达到64位,位数(最多64位)是任意的,起始位也是任意的。但是对于内部存储,我当然可以存储在适当的数据类型中,它可以适合这些位。
另外,我必须用同样的方法将它们从一个有效的数据打包到这个小的Big-Endian流中。:'(
我也不得不担心运行时和事实上,长是4字节。
所以要存储48位的值,我需要保持一个6字节的数组,以主机格式排列。没有编译器的支持。
编辑:64位long long支持;我刚刚查看了编译器手册。
有什么建议吗?我已经被困了三个星期了。

最佳答案

读取每个字节的流字节,在主机字节顺序中建立64位数字(即最大比特流长度)。
然后使用标准的位摆弄提取。
这两个步骤的食谱有一个好处是主机端不可知。
在索引处获取n位的窗口:

uint64_t extract(uint64_t in, int n, int i) {
    return in<<(64-i-n)>>(64-n);
}

07-24 18:48