位运算除法用于禁用除法指令的场景,仅对2的幂次可用右移替代;任意整数需模拟长除法,核心是“减法+移位”迭代,且必须用unsigned类型避免算术移位错误。

为什么不能直接用 / 却还要位运算做除法
实际场景中,比如嵌入式系统禁用浮点/除法指令、编译器优化关掉除法硬件支持,或在 JIT 编译器里需要手写可预测的整数除法逻辑时,/ 可能被禁止或不可靠。位运算本身不触发除法指令,但仅对 2 的幂次除数(如 ÷2、÷4、÷8)能直接用右移 >> 安全替代;任意整数除法必须模拟长除法过程,核心是「减法 + 移位」迭代。
unsigned int 除法:用移位和减法模拟长除法
无符号除法最直观,避免符号扩展和补码边界问题。基本思路是把被除数看作“当前余数”,从最高位开始试探:每次将除数左移到不超过余数的最大位置,减去它,并在对应位记 1。
关键点:
- 必须用
unsigned类型,否则右移是算术移位,高位补 1 会破坏逻辑 - 除数为 0 必须提前检查,否则死循环
- 用
32 - __builtin_clz(divisor)或手动找最高位可加速定位起始移位量,但非必需
简化版实现(仅处理 32 位):
int
-
INT_MIN取绝对值会溢出(因为abs(INT_MIN) == INT_MIN),必须用unsigned中间类型承接,例如:unsigned udiv = divisor - 结果是否需要处理溢出?
INT_MIN / -1在有符号下是未定义行为,位运算实现里应单独判断并返回INT_MAX或按需截断 - 不要用
std::abs对int直接调用,它不解决INT_MIN问题
性能和可移植性:别盲目替换 /
现代 x86/ARM CPU 的整数除法指令虽慢于加减移位,但已远好于几十次循环+分支。GCC/Clang 在 -O2 下对常量除数(如 /10)自动优化为乘法+移位,比手写位运算更优。只有以下情况值得手动实现:
- 目标平台确实没有除法指令(如某些 Cortex-M0)
- 需要确定性执行周期(实时系统)
- 在 constexpr 上下文里编译期求值(C++20 起支持部分循环)
另外,__builtin_clz、__builtin_ctz 等内置函数依赖编译器,裸机环境可能不可用,得回退到查表或逐位扫描。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











