切片 uint8_t 数组
Slice up an uint8_t array
假设我有一个 16 uint8_t
的数组,如下所示:
uint8_t array[] = {0x13, 0x01, 0x4E, 0x52, 0x31, 0x4A, 0x35, 0x36, 0x4C, 0x11, 0x21, 0xC6, 0x3C, 0x73, 0xC2, 0x41};
此数组存储包含在外设的128 位寄存器中的数据。它所代表的一些信息存储在2、3、8、12位……等等。
将它分割并位掩码我需要的信息的最好和优雅的方法是什么? (问题是我需要的一些东西与数组的一个单元格的长度重叠)
如果这能有所帮助,我写的这个片段将整个数组转换为 char* 字符串。但是将其转换为 int
不是选项,因为 .. 16 个字节。
int i;
char str[33];
for(i = 0; i < sizeof(array) / sizeof(*array) ; i++) {
sprintf(str+2*i,"%02hX",array[i]);
}
puts(str);
13014E52314A35364C1121C63C73C241
实际上,在尝试通过 LZ* 等算法解析各种比特流(如视频或图像文件或压缩数据)时也会出现此类问题。所以那里使用的方法是实现比特流 reader.
但在您的情况下,位序列的长度是固定的并且很短,因此一种方法是使用按位运算手动检查字段值。
或者您可以使用我刚刚编写的这个函数,它可以从 uint8 数组中提取任意数量的位,从所需的位位置开始:
uint32_t extract_bits(uint8_t *arr, unsigned int bit_index, unsigned int bit_count)
{
/* Assert that we are not requested to extract more than 32 bits */
uint32_t result = 0;
assert(bit_count <= sizeof(result)*8 && arr != NULL);
/* You can additionally check if you are trying to extract bits exceeding the 16 byte range */
assert(bit_index + bit_count <= 16 * 8);
unsigned int arr_id = bit_index / 8;
unsigned int bit_offset = bit_index % 8;
if (bit_offset > 0) {
/* Extract first 'unaligned_bit_count' bits, which happen to be non-byte-aligned.
* When we do extract those bits, the remaining will be byte-aligned so
* we will thread them in different manner.
*/
unsigned int unaligned_bit_count = 8 - bit_offset;
/* Check if we need less than the remaining unaligned bits */
if (bit_count < unaligned_bit_count) {
result = (arr[arr_id] >> bit_offset) & ((1 << bit_count) - 1);
return result;
}
/* We need them all */
result = arr[arr_id] >> bit_offset;
bit_count -= unaligned_bit_count;
/* Move to next byte element */
arr_id++;
}
while (bit_count > 0) {
/* Try to extract up to 8 bits per iteration */
int bits_to_extract = bit_count > 8 ? 8 : bit_count;
if (bits_to_extract < 8) {
result = (result << bits_to_extract) | (arr[arr_id] & ((1 << bits_to_extract)-1));
}else {
result = (result << bits_to_extract) | arr[arr_id];
}
bit_count -= bits_to_extract;
arr_id++;
}
return result;
}
下面是它的使用示例。
uint32_t r;
/* Extracts bits [7..8] and places them as most significant bits of 'r' */
r = extract_bits(arr, 7, 2)
/* Extracts bits [4..35] and places them as most significant bits of 'r' */
r = extract_bits(arr, 4, 32);
/* Visualize */
printf("slice=%x\n", r);
然后 r
的可视化由您决定。它们可以表示为十六进制双字、字符,也可以由您决定。
假设我有一个 16 uint8_t
的数组,如下所示:
uint8_t array[] = {0x13, 0x01, 0x4E, 0x52, 0x31, 0x4A, 0x35, 0x36, 0x4C, 0x11, 0x21, 0xC6, 0x3C, 0x73, 0xC2, 0x41};
此数组存储包含在外设的128 位寄存器中的数据。它所代表的一些信息存储在2、3、8、12位……等等。
将它分割并位掩码我需要的信息的最好和优雅的方法是什么? (问题是我需要的一些东西与数组的一个单元格的长度重叠)
如果这能有所帮助,我写的这个片段将整个数组转换为 char* 字符串。但是将其转换为 int
不是选项,因为 .. 16 个字节。
int i;
char str[33];
for(i = 0; i < sizeof(array) / sizeof(*array) ; i++) {
sprintf(str+2*i,"%02hX",array[i]);
}
puts(str);
13014E52314A35364C1121C63C73C241
实际上,在尝试通过 LZ* 等算法解析各种比特流(如视频或图像文件或压缩数据)时也会出现此类问题。所以那里使用的方法是实现比特流 reader.
但在您的情况下,位序列的长度是固定的并且很短,因此一种方法是使用按位运算手动检查字段值。
或者您可以使用我刚刚编写的这个函数,它可以从 uint8 数组中提取任意数量的位,从所需的位位置开始:
uint32_t extract_bits(uint8_t *arr, unsigned int bit_index, unsigned int bit_count)
{
/* Assert that we are not requested to extract more than 32 bits */
uint32_t result = 0;
assert(bit_count <= sizeof(result)*8 && arr != NULL);
/* You can additionally check if you are trying to extract bits exceeding the 16 byte range */
assert(bit_index + bit_count <= 16 * 8);
unsigned int arr_id = bit_index / 8;
unsigned int bit_offset = bit_index % 8;
if (bit_offset > 0) {
/* Extract first 'unaligned_bit_count' bits, which happen to be non-byte-aligned.
* When we do extract those bits, the remaining will be byte-aligned so
* we will thread them in different manner.
*/
unsigned int unaligned_bit_count = 8 - bit_offset;
/* Check if we need less than the remaining unaligned bits */
if (bit_count < unaligned_bit_count) {
result = (arr[arr_id] >> bit_offset) & ((1 << bit_count) - 1);
return result;
}
/* We need them all */
result = arr[arr_id] >> bit_offset;
bit_count -= unaligned_bit_count;
/* Move to next byte element */
arr_id++;
}
while (bit_count > 0) {
/* Try to extract up to 8 bits per iteration */
int bits_to_extract = bit_count > 8 ? 8 : bit_count;
if (bits_to_extract < 8) {
result = (result << bits_to_extract) | (arr[arr_id] & ((1 << bits_to_extract)-1));
}else {
result = (result << bits_to_extract) | arr[arr_id];
}
bit_count -= bits_to_extract;
arr_id++;
}
return result;
}
下面是它的使用示例。
uint32_t r;
/* Extracts bits [7..8] and places them as most significant bits of 'r' */
r = extract_bits(arr, 7, 2)
/* Extracts bits [4..35] and places them as most significant bits of 'r' */
r = extract_bits(arr, 4, 32);
/* Visualize */
printf("slice=%x\n", r);
然后 r
的可视化由您决定。它们可以表示为十六进制双字、字符,也可以由您决定。