~ 是位取反操作,对同一比特模式,int 解释为补码得负数,unsigned int 解释为正数,故输出不同;例如 ~1 在 32 位下为 0xFFFFFFFE,作 int 是 -2,作 unsigned int 是 4294967294。

为什么 ~ 对 unsigned int 和 int 的结果看起来不一样
因为 ~ 是纯位级操作,它不管符号,只翻转每一位;但你打印时,int 被解释为补码有符号数,而 unsigned int 直接当无符号整数读——同一串比特,解释方式不同,输出就差很远。
比如 int x = 1;,在 32 位系统上,x 的二进制是 00000000 00000000 00000000 00000001,~x 得到 11111111 11111111 11111111 11111110。若把它当 int 输出,就是 -2;若强制转成 unsigned int,就是 4294967294。
- 用
printf("%u", (unsigned int)~x)看无符号值 - 别直接对带符号整数做
~后再参与算术运算,容易溢出或逻辑错乱 - 如果目标是“取反后当掩码用”,优先声明为
unsigned类型
~ 在位掩码构造中常被误用的三种情况
写 ~(1 想清零第 n 位?没问题。但很多人没注意类型默认宽度和符号扩展问题。
-
1是int,在 16 位环境里~(1 可能触发未定义行为(左移超宽) ~(1U 更安全:1U是unsigned int,避免符号位干扰- 要操作 64 位掩码,得用
1ULL,否则~(1 在 32 位int上根本移不动
和 ! 混用导致逻辑翻车的典型现场
! 是逻辑非,只看“是否为 0”,返回 0 或 1;~ 是按位非,返回完整翻转后的整数值。两者语义完全不同,不能互换。
立即学习“C++免费学习笔记(深入)”;
-
if (~x)不等于if (x != 0):当x == -1时,~x == 0,整个条件为假,但x != 0为真 - 想判断“某标志位是否未设置”,该用
(flags & MASK) == 0,而不是~flags & MASK - 调试时打日志别写
cout 就跑,先确认你真需要那个大负数或大正数
在模板或泛型代码里用 ~ 前必须检查的两件事
模板参数类型不确定时,~T() 可能不合法,或者结果不符合预期。
- 确保
T支持位运算:static_assert(std::is_integral_v, "T must be integral"); - 考虑
T是否有符号:对char、short这类小整型,~会先整型提升(int),结果宽度可能和原类型不一致 - 如需保持位宽一致,显式转换:
static_cast(~static_cast<:make_unsigned_t>>(val))











