将 1-32 位插入 64 位(8x8 字节)缓冲区

Inserting 1-32 bits into a 64 bit (8x8byte) buffer

我正在尝试将 1 到 32 位长的值插入到 8 字节(64 位)的缓冲区中。

例如,我有 12 位值,我想将其插入位位置 7 到 18。

我能想到的唯一方法是将我的 12 位值转换为 64 位值,移动它,然后以这种方式设置缓冲区中的所有位,然后将我的 64 位值分成 8字节。 8 字节帧中可能还有其他数据... 有更好的方法吗?

下面将包含一些示例代码。

byte tx_msg[8] = {0};
uint32_t random_value = 77;
uint64_t buffer = 0;
// In this example, start point is bit 7, length is 12.

buffer = (uint64_t)random_value << (64 - 12 - 7);
for(int i = 0; i < 8; i++) {
    tx_msg[7-i] = tx_msg[7-i] | buffer >> (i*8);
}

首先你需要明确定义位序。假设位排序 LSB 在前:

| Byte0  | Byte1  | ...
-----------------------
|01234567|01234567| ...

例如:

|00000001|10000000|

将是 Byte0 == 0x80Byte1 == 0x08(因为十六进制表示是 MSB 在前)。

那么我会建议一个更通用的接口:

void copyBits( uint8_t* dest, int offset, uint32_t bits, int length ) ;

其中 bits 中的 length 位(从 LSB 开始)将被复制到 dest.

中的 offset

一个简单的(但在性能方面不是最优的)方法是逐位复制:

#include <stdint.h>
#include <stdlib.h>

void copyBits( uint8_t* dest, int offset, uint32_t bits, int length )
{
    for( int b = 0; b < length; b++ )
    {
        int source_bit = (bits & (0x01 << b)) == 0 ? 0 : 1 ;

        div_t bit_dest = div( offset + b, 8 ) ;
        if( source_bit == 0 )
        {
            dest[bit_dest.quot] &= ~(0x01 << bit_dest.rem) ;
        }
        else
        {
            dest[bit_dest.quot] |= (0x01 << bit_dest.rem) ;
        }
    }
}

这可以通过使用整个字节并在头部和尾部进行屏蔽来改进,但它更复杂,所以除非性能很关键或者你经常复制很多位,否则我建议简单和通用可能是充足的。无论哪种方式,带回家的是函数的通用可重用性,而不是针对特定参数的硬编码。重要的是它不限于 64 位目标缓冲区。它可以进行调整,因此它不限于最大 32 位源字段。

用法示例:

uint8_t x[8] = {0};

insertBits( x, 7, 0x555, 12 ) ;

for( int i = 0; i < sizeof( x ); i++ )
{
    printf( "%02X", x[i] ) ;
}

结果

80AA020000000000

二进制中 LSB 的第一位顺序是:

LSB --->
0000 0001 0101 0101 0100 0000 0000 ...
        ^-------------^
           0x555 (12 bits) copied here