Прежде всего вам необходимо четко определить порядок следования битов. Предполагая, что бит LSB упорядочивается первым:
| Byte0 | Byte1 | ...
-----------------------
|01234567|01234567| ...
Так, например:
|00000001|10000000|
будет Byte0 == 0x80
и Byte1 == 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) ;
}
}
}
Это можно улучшить, работая с целые байты и маскировка в голове и хвосте, но это более сложно, поэтому, если производительность не критична или вы часто копируете очень много битов, я полагаю, что простого и обобщенного c может быть достаточно. В любом случае, возвращение домой - это общее повторное использование функции c, а не жесткое кодирование для определенных c параметров. Важно отметить, что он не ограничен 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