位倒置是将整数低指定位宽的二进制位顺序完全翻转,必须手动实现,常见于FFT预处理、哈希索引等场景;需明确位宽(如8/16/32),不可直接对int整体操作;小位宽推荐查表法加速,大或非整倍位宽则用循环动态截断处理。

什么是位倒置,它在什么场景下必须手动实现
位倒置(Bit-Reversal)不是标准库函数,std::reverse 对字节有效但对单个整数的二进制位无效。它常用于 FFT(快速傅里叶变换)预处理、某些哈希或索引映射中——要求把一个 n 位整数的比特顺序完全翻转,比如 8 位的 0b00000101(5)变成 0b10100000(160)。
注意:倒置位宽必须明确。你不能对 int 整体倒置(符号位、填充位会干扰),而应指定有效位数,如 8/16/32 位。否则结果不可控。
用查表法加速 8 位和 16 位倒置
小位宽(≤16)查表最快,避免循环或位运算开销。核心是预先生成 uint8_t reverse_table[256],然后按字节拆分处理:
// 静态初始化查表(C++17 可 constexpr)
constexpr uint8_t reverse_table[256] = {
#define R2(n) n, n+2*64, n+1*64, n+3*64
#define R4(n) R2(n), R2(n+2*16), R2(n+1*16), R2(n+3*16)
#define R8(n) R4(n), R4(n+2*4), R4(n+1*4), R4(n+3*4)
R8(0), R8(2), R8(1), R8(3)
};
使用时:
- 8 位倒置:
reverse_table[x & 0xFF] - 16 位倒置:
(reverse_table[x & 0xFF] > 8) & 0xFF] - 务必先 & 掩码,防止高位污染查表索引
通用模板:对齐到 N 位的位倒置函数
当 N 不是 8 的倍数(如 10 位 FFT 索引),需动态截断。以下函数接受值 x 和位宽 bits(≤32),只倒置低 bits 位,高位清零:
uint32_t bit_reverse(uint32_t x, uint8_t bits) {
uint32_t r = 0;
for (uint8_t i = 0; i > i) & 1U) <p>关键点:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 循环次数由
bits决定,不是固定 32;否则对 10 位输入会错误倒置全部 32 位 - 末尾的
&截断必不可少——否则高位残留导致越界索引 - 若性能敏感且
bits固定,可将该函数特化为 constexpr 模板,编译期展开
用 __builtin_bitreverse* 编译器内置函数要注意平台限制
GCC/Clang 提供 __builtin_bitreverse32 等,但它们总是反转整个类型宽度(32 或 64 位),不支持任意位宽。直接用会出错:
比如想倒置 10 位的 0x00000123(二进制低 10 位是 000100100011),用 __builtin_bitreverse32(0x00000123) 得到的是全部 32 位翻转结果,而非仅低 10 位。
正确做法是:
- 先用掩码提取低
bits位:x & ((1U - 再调用 builtin 函数
- 最后右移补零或再次掩码(因为 builtin 返回的是完整 32 位,高位是原低位翻转后“溢出”的部分)
这反而比手写循环更易错,除非你确定位宽恒为 8/16/32 且无截断需求。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










