熟悉數據類型的大小、範圍與溢出規則,是編寫無 Bug C 代碼的基礎。本文匯總常見平台(32/64 位)下的類型大小與範圍,並通過實例分析有符號/無符號溢出的位級行為。
| 類型 | 字節數 | 備註 |
|---|---|---|
| char | 1 | 有符號性實現定義 |
| short | 2 | |
| int | 4 | 16位系統為2 |
| long | 4/8 | Windows 64位為4,Linux 64位為8 |
| long long | 8 | C99 標準 |
| float | 4 | IEEE 754 單精度 |
| double | 8 | IEEE 754 雙精度 |
| pointer | 4/8 | 隨架構 |
最佳實踐:永遠用 sizeof(T) 獲取當前平台大小,不要硬編碼。
| 類型 | 最小值 | 最大值 |
|---|---|---|
| signed char | -128 | 127 |
| unsigned char | 0 | 255 |
| signed short | -32,768 | 32,767 |
| unsigned short | 0 | 65,535 |
| signed int (32位) | -2,147,483,648 | 2,147,483,647 |
| unsigned int (32位) | 0 | 4,294,967,295 |
| signed long (64位) | -9.22e18 | 9.22e18 |
| float | ~ -3.4e38 | ~ 3.4e38 |
| double | ~ -1.7e308 | ~ 1.7e308 |
signed char c = 127;
c += 1; // UB!實際上大多數平台回繞為 -128
// 位級過程:01111111 + 1 = 10000000 (補碼表示 -128)
標準規定:有符號溢出屬 UB,編譯器可假設不發生並進行激進優化,**不可依賴回繞行為**。
unsigned char c = 255;
c += 1; // 保證結果為 0
// 位級:11111111 + 1 = 1 00000000 → 截取低 8 位 = 00000000
// 錯誤:int 溢出(假設 16 位 int)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365) // 31,536,000 > 32,767
// 正確:強制長整型運算
#define SECONDS_PER_YEAR (60L * 60 * 24 * 365) // 至少長整型
// 或 C99: (60 * 60 * 24 * 365LL)
口訣:常量表達式中**至少一個操作數加 L/LL/UL/ULL**,迫使整個表達式以長整型計算。
#define MAX_BUFFER_SIZE 1024;#define **不以分號結尾**,參數宏括號包裹:#define SQUARE(x) ((x)*(x));const / enum / constexpr (C++) 替代宏,擁有類型安全與作用域;SQUARE(i++) 會展開為 ((i++)*(i++)) 導致雙重自增。// 編譯期斷言 (C11)
_Static_assert(sizeof(int) == 4, "int must be 4 bytes");
_Static_assert(INT_MAX == 2147483647, "unexpected int range");
掌握類型範圍與溢出規則,能在編碼階段就消滅一大類隱蔽 Bug,也是面試、考研高頻考點。