4

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

11110000 10101010 11001100 

进入

像这样的数组

111100|001010|101011|001100

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

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

4

6 回答 6

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代替模数。只需在循环中使用此函数来填充您的目标数组。

于 2009-12-08T22:25:49.550 回答
1

您计算您的 5 位序列,读取每个字节,根据您的计数器和预期的字位置移动位(通过对相邻字节字进行异或运算),然后形成新的正确对齐的字节字,然后再进行处理。

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

于 2009-12-08T22:23:33.187 回答
1

您可以使用位摆弄来做到这一点:

#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
于 2009-12-08T22:29:26.763 回答
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);
于 2009-12-08T22:28:18.437 回答
0

我会考虑使用比特流。它将允许您一次读取一位。您可以将该位直接移动到位(使用<< n)。它的性能可能不如一次读取一个 8 位字节,但它肯定是看起来更干净的代码。

于 2009-12-08T22:56:34.693 回答
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;
}

设置by8Bitx会自动填写by6Bitx~~~

于 2009-12-09T00:02:51.000 回答