位运算与掩码:提取置位位对应原始值并压缩为8位输出方法
位提取实现方案
你这个需求是典型的**位压缩(并行位提取)**操作,针对16位输入、掩码固定恰好8位置1的硬件受限场景,不需要提前构建位置数组,有几个资源占用极低的可落地方案,按适用场景排序:
逐位遍历方案(通用、资源占用最低)
不需要额外存储掩码位置,从高位到低位遍历16个比特位,遇到掩码置1的位置就把输入对应位拼到结果里,全程只用基础移位、与、或操作,不管是MCU运行还是直接综合成数字逻辑,资源占用都最小。
可直接运行的代码如下,已经用你给出的测试用例验证过:
#include <stdio.h> #include <stdint.h> uint8_t compress_bits(uint16_t input, uint16_t mask) { uint8_t res = 0; uint8_t valid_cnt = 0; // 从最高位(bit15)到最低位(bit0)遍历,匹配示例的输出位顺序 for (int8_t i = 15; i >= 0; i--) { if (mask & (1U << i)) { res = (res << 1) | ((input >> i) & 1U); valid_cnt++; // 掩码固定8个1,取够8位直接终止,减少不必要的计算 if (valid_cnt == 8) break; } } return res; } int main() { uint16_t input = 23303; // 二进制0b0101101100000111 uint16_t mask = 13107; // 二进制0b0011001100110011 uint8_t fi = compress_bits(input, mask); // fi计算结果为115,和预期完全一致 printf("%u", fi); return 0; }
这个方案的特点:
- 零额外RAM占用,不需要数组存储掩码位位置,仅用3个8位临时变量
- 最多遍历16次,实际因为固定8位有效,遍历到最后一个置1位就会退出,执行效率足够
- 掩码动态变化也能正常处理,不需要预计算
硬编码直取方案(延迟最低,适合掩码固定场景)
如果你的掩码是产品定型后固定不变的,不需要运行时动态传入,可以直接提前把掩码置1的位偏移算好,硬编码成移位操作,没有循环、没有分支,单步出结果,延迟是所有方案里最低的。
对应你示例里的掩码0b0011001100110011,实现代码如下:
static inline uint8_t compress_fixed_mask(uint16_t input) { return ((input >> 6) & 0x80) | // 取bit13放到结果bit7 ((input >> 6) & 0x40) | // 取bit12放到结果bit6 ((input >> 4) & 0x20) | // 取bit9放到结果bit5 ((input >> 4) & 0x10) | // 取bit8放到结果bit4 ((input >> 2) & 0x08) | // 取bit5放到结果bit3 ((input >> 2) & 0x04) | // 取bit4放到结果bit2 (input & 0x02) | // 取bit1放到结果bit1 (input & 0x01); // 取bit0放到结果bit0 }
如果掩码是上电后才确定、之后不会变,也可以在上电初始化时跑一次遍历把每个位的偏移量存到8字节的RAM里,运行时直接用偏移量拼结果,比每次遍历快一点。
专用指令方案(仅作参考)
如果你用的CPU带位操作扩展指令,比如x86的PEXT、RISC-V B扩展的BCOMPRESS,单条指令就能完成位压缩操作,性能最高,但这类指令需要CPU硬件支持,资源受限的嵌入式场景一般不会带,按需选择即可。
验证说明:以上两个通用方案跑你给出的测试用例,返回值都是115(二进制
0b01110011),和你预期的压缩结果完全匹配。不需要额外做全16位的按位与操作,提取位的时候直接判断对应位即可,能省一个运算步骤。
内容的提问来源于stack exchange,提问作者bert29
相关产品推荐
相关产品推荐

