首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言 sizeof 深度解析:結構體對齊、陣列退化與常見誤區

     編輯:關於C語言

sizeof 是編譯期單目運算子(非函式),以**位元組**為單位回傳運算元的儲存大小。本文詳細說明操作數類型、優先順序、結構體記憶體對齊規則、陣列退化為指標的陷阱,以及跨平台可移植寫法。

基本語法與結果型別


sizeof(type)        // 型別需加括號
sizeof expression   // 運算式可不加括號
sizeof variable     // 變數可不加括號
// 結果型別:size_t (unsigned int),定義於 

❌ 不能用於:函式型別、不完整型別(未知大小陣列、前向宣告的結構/聯集)、void、位元欄位。

各類型 sizeof 規則

類型大小規則備註
char、signed char、unsigned char1ANSI 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) 改變)。

常見對齊值對照 (32 位系統)

型別大小對齊要求
char11
short22
int/long/float44
double88
指標44

陣列退化為指標:sizeof 失效經典案例


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 與運算子優先順序

sizeof 優先級為 2(高於乘除),可參與運算式:


int n = 5 * sizeof(int); // 合法
int x = sizeof int + 1;  // 合法,等同 (sizeof int) + 1

主要用途

  1. 動態記憶體配置:malloc(n * sizeof(Struct))、new T[n]。
  2. I/O 操作:fread(buf, sizeof(Record), count, fp)。
  3. 陣列元素計數:int count = sizeof(arr) / sizeof(arr[0])(僅適用於陣列未退化的作用域)。
  4. 結構體序列化/網路傳輸:確認封包大小,注意對齊差異導致跨平台不相容。

可移植建議

  • ✅ 所有涉及型別大小的計算**一律使用 sizeof**,勿硬編碼數字。
  • ✅ 跨平台資料交換定義 #pragma pack(1) 或使用定寬型別(int32_t、int64_t)並手動序列化。
  • ✅ 結構體成員按**大小遞減**排序(大型別在前),可減少填充位元組。
  • ✅ 使用 offsetof (stddef.h) 取得成員偏移,驗證對齊預期。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved