如何从字节可寻址数组中解析出n位元素

时间:2009-12-08 22:14:38

标签: c parsing bit-fields

我有一个只能以8位字节寻址的数据流,我想把它解析成6位元素并将其存储到数组中。有没有最知名的方法来做到这一点?

11110000 10101010 11001100 

这样的数组
111100|001010|101011|001100

(可以零填充,只需要以这种方式寻址)

并且数据是一个8位数组,也是6位的倍数,而不是真正无穷无尽的

6 个答案:

答案 0 :(得分:8)

取决于某个字节对特定体系结构的位数。在六位架构上,它非常简单: - )

假设每字节8位架构,你将不得不做一些事情:

int sixbits(unsigned char* datastream, unsigned int n) {
    int bitpos = n*6;
    return (datastream[bitpos/8] >> bitpos%8)    // lower part of the five bit group
        + (datastream[bitpos/8+1] << 8-bitpos%8) // if bitpos%8>2, we need to add some carry bits from the next char
        & 0x3f;                                  // and finally mask the lowest 6 bits
}

其中n是第n个6位组。任何体面的编译器都会用移位替换除法,用ands替换模数。只需在循环中使用此函数即可填充目标数组。

答案 1 :(得分:1)

计算5位序列,读取每个字节,根据计数器和预期的字位置(通过从相邻字节字中取出片段)移位位,然后形成新的正确对齐的字节字,然后处理。

我希望你不要指望代码......

答案 2 :(得分:1)

你可以使用bit fiddling来做到这一点:

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    unsigned char source[3] = { 15, 85, 51 };
    unsigned char destination[4];
    memset(destination, 0, 4);
    for (int i = 0; i < (8 * 3); ++i)
    {
        destination[i / 6] |= ((source[i / 8] >> (i % 8) & 1) << (i % 6));
    }

    for (int j = 0; j < 4; ++j)
        printf("%d ", destination[j]);
}

输出:

15 20 53 12

请注意,这将从五个最少有效位开始工作。

      15       85       51
11110000 10101010 11001100
111100 001010 101011 001100
    15     20     53     12

要获得最重要的信息,请改为:

destination[i / 6] |= ((source[i / 8] >> (7 - (i % 8))) & 1) << (5 - (i % 6));

这就像你的例子一样,假设你先写了最重要的一点:

240      170      204
11110000 10101010 11001100
111100 001010 101011 001100
60     10     43     12

答案 3 :(得分:0)

如何使用这样的结构:

struct bit5
{
    unsigned int v1 : 5;
    unsigned int v2 : 5;
    unsigned int v3 : 5;
    unsigned int v4 : 5;
    unsigned int v5 : 5;
    unsigned int v6 : 5;
    unsigned int v7 : 5;
    unsigned int v8 : 5;
}; 

然后将每个字节数组转换为struct bit5每8个字节(40位= 8组5位,适合8个字节)以获得5位块。说:

unsigned char* array; // a byte array that you want to convert
int i;
struct bit5* pBit5;

for(i = 0; i < (int)(SIZE_OF_ARRAY / 8); i++)
    pBit5 = (struct bit5*)((int)array + i * 8);

答案 4 :(得分:0)

我会考虑使用BitStream。它允许您一次读取一位。您可以将该位直接移位(使用&lt;&lt; n)。它可能无法一次读取8位字节,但它肯定会看起来更干净。

答案 5 :(得分:0)

这个联盟怎么样?

union _EIGHT_TO_SIX_ {

    struct {

       unsigned char by6Bit0 : 6;
       unsigned char by6Bit1 : 6;
       unsigned char by6Bit2 : 6;
       unsigned char by6Bit3 : 6;

    } x6;

    struct {

       unsigned char by8Bit0;
       unsigned char by8Bit0;
       unsigned char by8Bit0;

    } x8;
}

设置byBitx将自动填入6Bitx ~~~