sizeof 是編譯期單目運算子(非函式),以**位元組**為單位回傳運算元的儲存大小。本文詳細說明操作數類型、優先順序、結構體記憶體對齊規則、陣列退化為指標的陷阱,以及跨平台可移植寫法。
sizeof(type) // 型別需加括號
sizeof expression // 運算式可不加括號
sizeof variable // 變數可不加括號
// 結果型別:size_t (unsigned int),定義於
❌ 不能用於:函式型別、不完整型別(未知大小陣列、前向宣告的結構/聯集)、void、位元欄位。
| 類型 | 大小規則 | 備註 |
|---|---|---|
char、signed char、unsigned char | 1 | ANSI C 保證 |
short、int、long、float、double、long double | 實作定義 | 32 位系統常見:2/4/4/4/8/10/12 |
| 指標 | 實作定義 | 近/遠指標 2/4/8 位元組 |
| 陣列 | 元素大小 × 元素總數 | 包含所有維度 |
| 結構體 | 所有成員大小 + 填充位元組 | 受對齊規則影響 |
| 聯集 | 最大成員大小(對齊後) |
編譯器為了 CPU 存取效率,要求成員位址滿足對齊條件:位址偏移量必須是該型別大小的倍數(或編譯器指定的打包值)。
struct MyStruct {
double d; // 8 位元組,偏移 0 (8 的倍數)
char c; // 1 位元組,偏移 8 (1 的倍數)
int i; // 4 位元組,偏移 9 → 需填充 3 位元組至 12 (4 的倍數)
}; // 結構體大小 = 16 (8 的倍數,最大成員對齊)
VC++ 6.0 / VS 預設對齊值為 8(可用 #pragma pack(n) 改變)。
| 型別 | 大小 | 對齊要求 |
|---|---|---|
| char | 1 | 1 |
| short | 2 | 2 |
| int/long/float | 4 | 4 |
| double | 8 | 8 |
| 指標 | 4 | 4 |
void Func(int arr[10]) { // 參數實為 int* arr
printf("%zu\n", sizeof(arr)); // 輸出 4/8 (指標大小),非 40!
}
int main() {
int a[10];
printf("%zu\n", sizeof(a)); // 輸出 40 (完整陣列)
Func(a);
}
解決:傳遞陣列大小作為額外參數,或使用結構體包裹陣列(struct Arr { int a[10]; }),或 C++ 改用 std::array/std::vector。
sizeof 優先級為 2(高於乘除),可參與運算式:
int n = 5 * sizeof(int); // 合法
int x = sizeof int + 1; // 合法,等同 (sizeof int) + 1
malloc(n * sizeof(Struct))、new T[n]。fread(buf, sizeof(Record), count, fp)。int count = sizeof(arr) / sizeof(arr[0])(僅適用於陣列未退化的作用域)。sizeof**,勿硬編碼數字。#pragma pack(1) 或使用定寬型別(int32_t、int64_t)並手動序列化。offsetof (stddef.h) 取得成員偏移,驗證對齊預期。