我目前正在做一个项目,我必须为嵌入式系统实现Elias Gamma编码(STM32F405使用C编程). 主要的优先级是代码的效率和速度,因此我实现了Elias Gamma编码的查找表,其中包含每个"位数组"的位值和位数(我使用uint 32_t表示符号,uint 8_t表示长度). 然而,我遇到了问题,这些位转换成字节array.下面是一个我正在try 做的事情的例子.

对于三个符号—0b0001001(比特长度7),0b011(比特长度3),b000010001(比特长度9),我必须得到0b00100110000100001,因此0x12 0xC2 0x20作为字节数组,以通过通信信道,如USART传输数据.>

让我困惑的是,位符号的长度不同,并且在使用字节作为最小数据 struct 的平台中,必须将"追加"过程应用到位上.

有没有一个简单的方法来做到这一点?

编辑: 为清楚起见,我try 将4096个"位数组"附加到X个字节.X数取决于附加的总位数(在处理过程中未知).

推荐答案

解决方案要求:

// Returns false if nothing left.
int get_next_bits( uint8_t *len, uint32_t *bits );

// Sends the first `output_len` bytes pointed by `output`.
send_buffer( uint16_t output_len, const uint8_t *output );

// Allocated memory or array large enough for output.
// See below if this can't be guaranteed.
uint8_t *buf;

解决方案:

uint16_t output_len = 0;
uint8_t *output = buf;     // Assumed to be large enough. But see below.
uint8_t available = 0;     // Number of unassigned bits in `*output`.
uint32_t bits;             // Bits to add to output.
uint8_t unassigned;        // Number of bits (left) in `bits`.

while ( get_next_byte( &unassigned, &bits ) ) {
   while ( unassigned > 0 ) {
      if ( available == 0 ) {
         // We need another byte of output.
         // `output` already points to this byte.
         ++output_len;
         *output = 0;
         available = 8;
      }

      if ( available <= unassigned ) {
         // We get here, for example, when we have
         // 5 bits to insert but only 3 bits available in current output byte.
         // So we shift the unassigned bits by 2 to place into position.
         // And we're left 使用 0 available bits and 2 unassigned bits.
         // We can't forget to "remove" from `bits` the 3 bits we assigned.
         uint8_t shift = unassigned - available;
         *output |= bits >> shift;
         unassigned = shift;
         bits &= 0xFF >> ( 8 - unassigned );
         available = 0;
         ++output;
      } else {
         // We get here, for example, when we have
         // 3 bits to insert and 5 bits available in current output byte.
         // So we shift the unassigned bits by 2 to place into position.
         // And we're left 使用 2 available bits and 0 unassigned bits.
         uint8_t shift = available - unassigned;
         *output |= bits << shift;
         unassigned = 0;
         available = shift;
      }
   }
}

send_buffer( output_len, output );

如果需要,available == unassigned箱可以特别处理.

if ( available == unassigned ) {
   // We get here, for example, when we have
   // 5 bits to insert and 5 bits available in current output byte.
   // We're left 使用 0 available bits and 0 unassigned bits.
   *output |= bits;
   unassigned = 0;
   available = 0;
   ++output;
}

如果不能保证缓冲区足够大以容纳所有位,请替换

if ( available == 0 ) {
   // We need another byte of output.
   // `output` already points to this byte.
   *output = 0;
   available = 8;
   ++output_len;
}

使用

if ( available == 0 ) {
   // We need another byte of output.
   // `output` already points to this byte.

   if ( output_len == buf_size ) {
      // Buffer is full, so send and empty it.
      output -= buf_size;
      output_len = 0;
      send_buffer( buf_size, output );
   }

   *output = 0;
   available = 8;
   ++output_len;
}

C++相关问答推荐

如何将匿名VLA分配给指针?

Zig将std.os.argv转换为C类型argv

为什么静态说明符为内联函数生成外部定义?

当main函数调用被重构时,C函数给出错误的结果

难以理解Makefile隐含规则

在没有动态内存分配的情况下,用C语言最快地将各种数组复制到单个较大的数组中

将 struct 变量赋给自身(通过指针取消引用)是否定义了行为?

LibpCap禁用监视器模式(C、MacOS)

C语言编译阶段与翻译阶段的关系

为什么我不能只在内存地址中添加一个int来寻址任何数组?

CC2538裸机项目编译但不起作用

不同出处的指针可以相等吗?

Valgrind用net_pton()抱怨

隐藏测试用例无法在c程序中计算位数.

强制GCC始终加载常量(即只读),即使启用了优化

在分配内存后使用指针是未定义的行为吗?

既然我们在 if 中将 int 的值更改为 10,为什么在第二个 fork 后,子进程及其创建的子进程都会打印 33 ?

Struct 内的数组赋值

C 中从 Unix 纪元时间转换的损坏

段错误try 访问静态字符串,但仅有时取决于构建环境