因为+和-是纯计算操作,无赋值语义;原地加减需复合赋值(如a+=b)或位运算模拟全加器:用异或得本位和、与加左移得进位,循环至进位为0。

为什么不能直接用 + 和 - 做“原地加减”?
所谓“原地”,是指不借助额外变量(比如中间缓存、临时寄存器)完成两个整数的加减,且结果仍存回其中一个操作数。C++ 的 + 和 - 本身是纯计算操作,不带赋值语义;想“原地”,得靠复合赋值(如 a += b),但这底层仍依赖 ALU 加减电路,并非位运算实现。真要用位运算从零构造加法,核心是模拟二进制全加器:把进位和本位分开处理,迭代直到无进位。
add 函数怎么用位运算循环实现?
标准做法是用异或(^)算不带进位的和,用与(&)左移()算进位,重复直到进位为 0。注意:必须用无符号类型避免右移符号扩展问题,且需处理负数补码表示。
实操建议:
- 用
unsigned int或uint32_t封装输入,避免负数左移未定义行为 - 循环中先算
sum = a ^ b,再算carry = (a & b) ,然后更新 <code>a = sum,b = carry - 当
b == 0时退出,此时a即为和 - 若原始输入含负数,函数返回前需做符号还原(例如强转回
int)
int bit_add(int a, int b) {
while (b != 0) {
int sum = a ^ b;
int carry = (unsigned int)(a & b) << 1;
a = sum;
b = carry;
}
return a;
}
sub 能否只靠位运算不调用 add?
可以,但没必要绕开 add。因为减法本质是加负数,而负数在补码中等于取反加 1:-x == ~x + 1。所以 a - b 等价于 a + (~b + 1)。直接复用上面的 bit_add 最稳妥。
立即学习“C++免费学习笔记(深入)”;
常见错误现象:
- 写成
a + ~b忘记加 1 → 结果小 1 - 对
INT_MIN取反后加 1 溢出 → 实际中应限制输入范围或用更大类型暂存 - 用
int直接左移负数 → 触发未定义行为(UB)
性能和实际使用要注意什么?
位运算加法比硬件加法慢得多:现代 CPU 的 add 指令是单周期,而位运算循环平均要 3–30 次迭代(取决于进位链长度)。它没有实用性能优势,仅用于理解补码、面试题或极特殊嵌入式场景(如某条加法指令被禁用)。
真正容易被忽略的点:
-
carry左移可能溢出,必须用足够宽的无符号类型承载(如用uint64_t处理两个int32_t) - 编译器优化可能把整个循环识别为加法并替换成
add指令,导致你以为在“位运算”,其实没生效 - 无法处理浮点数、大整数或自定义类型——位运算是整数补码层面的操作,和语义无关


















