C++ 中有符号与无符号类型混用可能导致的问题

问题现象

先看一段看似人畜无害的代码:

cpp 复制代码
#include <iostream>

int main() {

    unsigned a{ 10 };
    int b{ -1 };
    auto res = a * b;
    std::cout << "a*b=" << res << std::endl;

    return 0;
}

输出不是 -10,而是 4294967286。是不是开始怀疑编译器了?别急,这不是 Bug,而是 C++ 类型转换规则在你眼皮底下悄悄偷换了概念。

原因剖析

当有符号和无符号整数参与同一次算术运算时,C++ 会执行算术转换:

  • 若两者的秩(rank)相同 ,且其中一个为无符号、另一个为有符号,则有符号类型会转换为无符号类型。

回到上面的例子:b = -1 先被转换为 unsigned int。在 32 位补码体系下,-1 的二进制为 11111111 11111111 11111111 11111111,解释成无符号整数就是 4294967295 。这个数乘以 10 必然溢出,最终结果按模2322^{32}232取余,得到 4294967286。

v.size() - 1 的经典翻车现场

更隐蔽的坑藏在日常代码里。C++ 标准库容器的 size() 返回的是无符号整数 。如果容器为空,v.size() 返回 0,而 0 - 1 会按照上述规则得到一个巨大的正整数(例如 SIZE_MAX),导致循环执行约 2^64 次,直接卡死程序。

cpp 复制代码
for (size_t i = 0; i < v.size() - 1; i++) 
    // 实际业务

正确的做法是提前判断容器是否为空,或者直接把 v.size() 转为有符号类型(在确保不会溢出的前提下)。

总结规律:记住这两条,避开所有同类坑

两个不同类型的操作数做算术运算时,编译器会先执行类型转换,再计算:

  1. 秩不相等:低秩类型 → 高秩类型。
  2. 秩相等且符号不同:无符号类型若能容纳有符号类型的全部取值,则有符号 → 无符号。

附常见整型的秩排序(由高到低):

bash 复制代码
long long == unsigned long long > long == unsigned long > int == unsigned int > short == unsigned short > char == unsigned char

下次看到 -1 与无符号数一起出现时,记得多留个心眼。

相关推荐
十年Java程序媛1 小时前
Redis 分布式锁 + GZIP 压缩缓存踩坑|高并发缓存真实线上复盘
java·开发语言·spring boot·redis·分布式·缓存·面试
垆边人似月.1 小时前
华为题:滑动窗口最大值
数据结构·c++·算法
菩提树下的凡夫1 小时前
OPenCV4.8与OpenCV5.0的区别
c++·opencv
要练八块腹肌2 小时前
map和set介绍与使用
c++
for_ever_love__2 小时前
LangChain Token 计数与成本控制:先知道钱花在哪
开发语言·langchain
m0_547486662 小时前
《数据结构 (C语言)》期末试卷及答案(10套)2026版
c语言·开发语言·数据结构
Sand(ContextGate)2 小时前
从开发者调试工具到消费级 App:一个 AI 电商导购项目的 C 端改造与 6 个连环踩坑实录
开发语言·人工智能·python·ai·langchain
白杨尚青2 小时前
C++入门篇(十七):priority_queue 完整模拟实现——仿函数、区间建堆与指针特化(附完整代码仓库)
开发语言·c++·stl·仿函数
逐光者9332 小时前
滤波器的 R 与 C 如何选择:从截止频率到工程实践
c语言·开发语言·r语言