有符号数与无符号数的转换
核心思想
有符号数与无符号数之间的转换遵循一个基本原则:位模式不变,解读方式改变。硬件不做任何位级别的修改,仅改变对同一组比特位的解释方式。
转换规则
无符号数 → 有符号数(补码)
若 ,则转换后数值不变;否则转换后的值为 。
有符号数 → 无符号数
若 ,则转换后数值不变;否则转换后的值为 。
图示关系
无符号数范围: 0 ---------- 2^{w-1} ------------- 2^w - 1
| | |
| ↓ |
有符号数范围: TMin ---------- 0 ---------- TMax |
| (对应 2^{w-1}) |
↓ ↓
负数部分映射到 正数部分数值保持不变
高端的无符号数区域
例如,8位下:
-1(有符号)→255(无符号)——位模式均为11111111128(无符号)→-128(有符号)——位模式均为10000000
隐式转换的陷阱(重要!)
C语言中,当有符号数和无符号数出现在同一个表达式中时,有符号数会隐式转换为无符号数。这是许多难以发现的bug的根源。
典型Bug:死循环
for (size_t i = n - 1; i >= 0; i--) { // size_t 是无符号类型
// ...
}当 i 减到 0 后再减 1 会变成最大的正数(因为无符号数下溢),导致死循环。
典型Bug:比较操作
int a = -1;
unsigned int b = 0;
if (a < b) {
// 这里的判断不成立!因为 -1 被隐式转换为 UINT_MAX
}最佳实践
- 尽量避免在有符号数和无符号数之间进行比较和运算
- 使用
-Wsign-compare等编译选项来检测此类问题 - 循环变量递减时注意0的边界情况
相关笔记
链接到
- 上一个知识点:2.3 整型数表示
- 下一个知识点:2.5 整型的扩展与截断