前两天review一段老代码,看见有人写了个 for(unsigned i = n; i >= 0; i–)。我当时就笑了——这循环根本停不下来。unsigned减到0再往下走,回绕成 UINT_MAX,i>=0恒成立,死循环一个。编译器一声不吭,连 warning 都懒得给,release下跑得欢实得很。
更阴的是 signed 跟 unsigned 混着比。int a = -1; unsigned b = 1; 结果 a < b 竟然是 false。比较前先整型提升,a 被当成超大正数,负号瞬间蒸发,不等号方向整个反了。这种 bug 编译无警告、运行不崩,全靠边界条件偶发,线上基本复现不出来,只能靠人肉瞪眼去逮。我见过有人拿 int 下标去跟 size_t 的容器 size() 比,负数索引直接变成天文数字,越界读写静悄悄。
我后来养成习惯:循环计数和数组下标一律用有符号。真要碰无符号,先把边界在脑子里过一遍。少掉几根头发比什么都强。