如何将任意位宽(如5位)元素无填充打包到unsigned char数组中
无填充任意位宽元素写入unsigned char数组方案
实现逻辑
要实现任意位宽元素无填充写入uint8_t数组,核心是拆分写入位置的字节偏移和位偏移,逐字节处理跨字节的写入需求:
- 计算当前待写入元素的全局起始位位置,拆分得到对应的数组字节索引、当前字节内的起始位偏移
- 优先占用当前字节剩余的空闲位,剩余的待写入位自动顺延到下一个字节处理,循环直到所有位写入完成
- 全程操作uint8_t类型指针,没有位宽上限,不存在宽指针延后问题
完整可运行代码
#include <stdio.h> #include <stdint.h> #include <string.h> # define VALUE_1_SIZE_BITS 2 # define VALUE_2_SIZE_BITS 3 // 单个元素总占位数 # define ELEM_TOTAL_BITS (VALUE_1_SIZE_BITS + VALUE_2_SIZE_BITS) # define FREE_BYTES 5 struct delta_measurement_struct { unsigned delta_time: VALUE_1_SIZE_BITS; unsigned delta_sensor_data: VALUE_2_SIZE_BITS; } __attribute__((packed)); // 避免结构填充 void data_struct_array_set(uint8_t *t, unsigned idx, struct delta_measurement_struct delta_measurement) { // 合并元素值,先做位掩码过滤,避免无效高位污染数据 const unsigned v = ((delta_measurement.delta_time & ((1U << VALUE_1_SIZE_BITS) - 1)) << VALUE_2_SIZE_BITS) | (delta_measurement.delta_sensor_data & ((1U << VALUE_2_SIZE_BITS) - 1)); unsigned remaining_bits = ELEM_TOTAL_BITS; unsigned current_val = v; // 计算写入起始位置 unsigned start_bit = ELEM_TOTAL_BITS * idx; unsigned byte_idx = start_bit / 8; unsigned bit_in_byte = start_bit % 8; while (remaining_bits > 0) { // 当前字节剩余可写入位数 unsigned curr_avail = 8 - bit_in_byte; // 本次实际写入位数 unsigned write_cnt = remaining_bits < curr_avail ? remaining_bits : curr_avail; unsigned write_mask = (1U << write_cnt) - 1; // 写入当前字节 t[byte_idx] |= (current_val & write_mask) << bit_in_byte; // 更新状态变量 current_val >>= write_cnt; remaining_bits -= write_cnt; byte_idx++; bit_in_byte = 0; } } int main() { uint8_t delta_measurements[FREE_BYTES]; memset(delta_measurements, 0, sizeof(delta_measurements)); // 计算可写入的元素总数 unsigned max_elems = (FREE_BYTES * 8) / ELEM_TOTAL_BITS; for (int i = 0; i < max_elems; ++i) { printf("写入第%d个元素,占%d位\n", i+1, ELEM_TOTAL_BITS); data_struct_array_set(delta_measurements, i, (struct delta_measurement_struct) {3, 7}); printf("数组当前值:0x"); for (int j = 0; j < FREE_BYTES; ++j) { printf("%02X-", delta_measurements[j]); } printf("\n"); } return 0; }
使用说明
你可以根据需求修改VALUE_1_SIZE_BITS、VALUE_2_SIZE_BITS调整单元素的位宽,修改FREE_BYTES调整存储数组的大小,代码会自动处理跨字节写入的逻辑,不需要手动调整字节索引。
内容的提问来源于stack exchange,提问作者HennyKo
相关产品推荐
相关产品推荐

