将1-32位插入64位(8x8byte)缓冲区

问题描述 投票:-1回答:1

我正在尝试将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);
}
c++ embedded buffer bit
1个回答
0
投票

首先,您需要明确定义位的顺序。假设先按位排序LSB:

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

例如:

|00000001|10000000|

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

然后,我建议一个更通用的界面:

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

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

一种简单的(但在性能方面不是最佳的方法是这样逐位复制:

#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
© www.soinside.com 2019 - 2024. All rights reserved.