C語言中signed與unsigned混合運算是導致難以發現Bug的高發區。本文系統梳理整型提升規則、經典面試題陷阱、溢出行為差異,並提供避坑最佳實踐,助你寫出類型安全的健壯代碼。
原因:
-1是int,與unsigned int運算時,int提升為unsigned int變為4294967295,相乘結果取模2^32得4294967293。整型提升規則完整體系
1. 整型提升(小類型→int/unsigned int)
char、short、_Bool、位域 → int(若能表示所有值)否則unsigned int2. 常用算術轉換(雙操作數統一類型,按優先級):
long double → 另一操作數轉為long doubledouble → 另一操作數轉為doublefloat → 另一操作數轉為float| 類型 | 位寬 | 範圍 | 精度級別 |
|---|---|---|---|
| char | 8 | -128~127 | 最低 |
| unsigned char | 8 | 0~255 | |
| short | 16 | -32768~32767 | 低 |
| unsigned short | 16 | 0~65535 | |
| int | 32 | -2^31~2^31-1 | 中 |
| unsigned int | 32 | 0~2^32-1 | |
| long | 32/64 | 平台相關 | 高 |
| unsigned long | 32/64 | 平台相關 | |
| long long | 64 | -2^63~2^63-1 | 最高 |
| unsigned long long | 64 | 0~2^64-1 |
場景1:unsigned int + int
場景2:unsigned int + long(32位系統)
// 字面量類型規則(十進制無後綴) 123 // int 1234567890123 // long/long long -1 // int (非unsigned!) 0xFFFFFFFF // unsigned int (十六進制首選無符號)有符號溢出 vs 無符號溢出
| 特性 | 有符號溢出 | 無符號溢出 |
|---|---|---|
| 標準規定 | 未定義行為(UB) | 定義良好:模2^N環繞 |
| 編譯器優化 | 可假設不發生優化 | 不可假設不發生 |
| 典型表現 | 環繞/崩潰/刪除代碼 | 確定環繞 |
| 檢測工具 | UBSan(-fsanitize=undefined) | 通常不報警 |