我有一个只能以 8 位字节寻址的数据流,我想将其解析为 6 位元素并将其存储到一个数组中。有没有最知名的方法可以做到这一点?
11110000 10101010 11001100
进入
像这样的数组
111100|001010|101011|001100
(可以有零填充,只需要以这种方式寻址)
并且数据是一个 8 位数组,也是 6 位的倍数,并不是真的无穷无尽
我有一个只能以 8 位字节寻址的数据流,我想将其解析为 6 位元素并将其存储到一个数组中。有没有最知名的方法可以做到这一点?
11110000 10101010 11001100
进入
像这样的数组
111100|001010|101011|001100
(可以有零填充,只需要以这种方式寻址)
并且数据是一个 8 位数组,也是 6 位的倍数,并不是真的无穷无尽
取决于您的特定架构上一个字节有多少位。在六位架构上它非常简单:-)
假设每字节 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代替模数。只需在循环中使用此函数来填充您的目标数组。
您计算您的 5 位序列,读取每个字节,根据您的计数器和预期的字位置移动位(通过对相邻字节字进行异或运算),然后形成新的正确对齐的字节字,然后再进行处理。
我希望你不要期望代码......
您可以使用位摆弄来做到这一点:
#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
如何使用这样的结构:
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);
我会考虑使用比特流。它将允许您一次读取一位。您可以将该位直接移动到位(使用<< n)。它的性能可能不如一次读取一个 8 位字节,但它肯定是看起来更干净的代码。
这个联盟怎么样?
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~~~