int反转易溢出,因res*10中间步骤可能越界触发未定义行为;须在乘10前检查res是否超过INT_MAX/10或低于INT_MIN/10,相等时再判个位;-2147483648等边界用例要求条件完备。

为什么 int 反转容易溢出,必须提前判断
直接逐位取模再拼接(res = res * 10 + x % 10)时,res * 10 这一步就可能溢出 —— 即使最终结果合法,中间计算已越界。C++ 对有符号整数溢出是未定义行为(UB),编译器可能优化掉你的判断逻辑。
正确做法是:在乘 10 前检查 res 是否超过 INT_MAX / 10 或低于 INT_MIN / 10;若相等,再单独判断个位是否会导致溢出。
if (res > INT_MAX / 10 || (res == INT_MAX / 10 && x % 10 > 7)) return 0;if (res- 注意:
INT_MAX % 10 == 7,INT_MIN % 10 == -8(因为INT_MIN是 -2147483648)
std::abs 在反转负数时的陷阱
对 INT_MIN 调用 std::abs(INT_MIN) 会溢出 —— 因为 INT_MIN 比 INT_MAX 绝对值大 1(-2147483648 vs 2147483647)。所以不能先取绝对值再反转。
安全做法是统一用 int 类型处理符号:每次取 x % 10(C++ 中负数取模结果符号跟随被除数),然后累加到带符号的 res 中。
立即学习“C++免费学习笔记(深入)”;
- 例如:
x = -123→x % 10是-3,不是7 - 保持原符号参与运算,避免
abs、long long等额外类型转换 - 只要溢出检查到位,全程用
int就够
完整可运行的反转逻辑(不依赖 long long)
以下代码只用 int,通过前置边界检查规避所有溢出风险:
int reverse(int x) {
int res = 0;
while (x != 0) {
int digit = x % 10;
if (res > INT_MAX / 10 || (res == INT_MAX / 10 && digit > 7)) return 0;
if (res < INT_MIN / 10 || (res == INT_MIN / 10 && digit < -8)) return 0;
res = res * 10 + digit;
x /= 10;
}
return res;
}
关键点:
- 每次循环只做一次取模、一次除法、一次乘加,无冗余操作
- 边界检查放在更新
res前,覆盖正负两种溢出路径 - 不用
string或额外容器,空间 O(1),时间 O(log n)
测试时最容易漏掉的两个用例
很多实现能过常规数据,但栽在这两个上:
-
reverse(1534236469)→ 应返回0(反转后 9646324351 >INT_MAX) -
reverse(-2147483648)→ 应返回0(即INT_MIN,其绝对值无法表示为int,且反转后也溢出)
这两个用例直击取模逻辑和溢出判断的完整性 —— 少一个条件分支,就挂。
