负数赋给unsigned int按模运算转换为极大正数,如-1转为4294967295(32位)或255(8位),非底层位 reinterpret;混用有符号与无符号时,隐式提升致逻辑错误,循环易成无限。

负数赋给 unsigned int 不会报错,但值会变成一个极大正数——这不是“错误”,而是标准定义的行为,本质是模运算(modulo)。
赋值时实际发生的是取模,不是截断或补码转换
当你写 unsigned int x = -1;,C++ 标准规定:结果等于 -1 % UINT_MAX + 1,即 -1 对该类型能表示的数值总数(2^N)取模后的非负余数。对 32 位 unsigned int 来说,就是 -1 % 4294967296,结果为 4294967295。
- 这个过程与底层补码存储无关——即使你换用不同 ABI 或平台,只要类型宽度一致,结果就确定
- 不要误以为是“把
int的二进制位直接 reinterpret 为unsigned”;标准明确要求按数学模运算定义 -
unsigned char c = -1;得到255,因为-1 % 256 == 255,和位宽严格对应
混用有符号和无符号变量时,隐式转换更危险
算术表达式中只要出现 unsigned,所有操作数都会被提升为无符号类型再计算,int 负值会先转成大正数,再参与运算。
unsigned u = 10; int i = -42; std::cout 输出 <code>4294967264(假设 32 位int),不是-32if (len - offset 中若 <code>len和offset是size_t(即unsigned),整个条件永远为假,分支永不执行- 编译器通常不警告这类转换,GCC/Clang 需加
-Wsign-conversion才可能捕获
循环中用 unsigned 做递减计数器极易死循环
这是最常被忽略的实际陷阱:条件判断依赖 或 <code>>= 时,unsigned 永远不会“小于 0”。
立即学习“C++免费学习笔记(深入)”;
-
for (unsigned i = 10; i >= 0; --i)是无限循环——当i减到0后再执行--i,得到的是UINT_MAX,条件仍为真 - 正确写法应是
i > 0并从i = 10开始,或改用带符号类型(如int) - STL 容器的
size()返回size_t,直接用于反向遍历(如for (auto i = v.size(); i >= 0; --i))同样踩坑
真正难防的不是赋值那一刻的“大数”,而是后续表达式里它悄无声息地拉拢其他操作数一起变成无符号,让逻辑彻底偏离预期。检查所有涉及 unsigned 的比较、循环边界和算术运算,比盯着单个赋值更重要。


















