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

深度解析C語言sizeof操作符:核心規則、常見陷阱與實戰應用

     編輯:關於C

sizeof 是 C 語言中的一元操作符(而非函數),用於在編譯期確定類型或表達式的存儲大小(以字節為單位)。其結果類型為 size_t(通常為 unsigned int 或 unsigned long)。掌握 sizeof 的行為細節,對於內存管理、序列化、跨平台移植及性能優化至關重要。

基本語法與操作數形式

  • 類型操作數:sizeof(int)、sizeof(struct Foo) —— 必須加括號。
  • 表達式操作數:sizeof variable、sizeof arr[0] —— 變量名可不加括號,但加上也無妨。
  • 不求值特性:操作數表達式不會在運行時求值(如 sizeof(i++) 不會修改 i)。

不同類型的 sizeof 結果規則

基本類型

  • char、signed char、unsigned char:恆為 1(C 標準保證)。
  • short、int、long、long long、浮點類型:實現定義,常見於 32/64 位系統的差異(如 long 在 Windows 64 位為 4 字節,Linux 64 位為 8 字節)。
  • void、不完全類型(未知大小數組、前向聲明的結構體)、位域:禁止使用,編譯報錯。

指針類型

sizeof(T*) 等於平台指針大小:32 位系統通常為 4,64 位系統通常為 8。與指向的類型 T 無關。

數組類型

  • 靜態數組:int a[10]; sizeof(a) == 10 * sizeof(int) —— 獲得整個數組大小,不退化為指針。
  • 動態分配/形參數組:int *p = malloc(10*sizeof(int)); sizeof(p) == sizeof(int*);函數參數 void f(int a[]) 實際為指針,sizeof(a) 返回指針大小。

結構體與聯合體

  • 結構體:包含所有成員大小 + 填充字節(為滿足對齊要求)。sizeof(struct S) ≥ 成員大小之和。
  • 聯合體:等於最大成員的大小(含對齊填充)。
  • 靜態成員:不計入結構體大小,因其存儲於全局/靜態區。
  • 空結構體:C 標準禁止,GNU 擴展允許且 sizeof == 0;C++ 中為 1。

九大核心注意點

  1. 結果類型:size_t,無符號,格式化輸出用 %zu(C99)或 %lu 配合強轉。
  2. 編譯期常量:可用於數組維度定義、#if 預處理條件(配合常量表達式)。
  3. 類型操作數必加括號:sizeof(int) ✓,sizeof int ✗。
  4. 數組不退化:只有數組類型的 sizeof 返回整體大小,其他上下文(如傳參、賦值)才退化為指針。
  5. 對齊與填充:結構體大小受 #pragma pack(n)、編譯器屬性 __attribute__((packed)) 影響,跨平台傳輸需显式處理。
  6. VLA(變長數組):C99 支持,sizeof 在運行時求值(僅此例外),sizeof(int[n]) 依賴 n 的運行時值。
  7. 字符串字面量:sizeof("abc") == 4(含結束符 \0),不同於 strlen("abc") == 3。
  8. 位域不可用:sizeof(bf) 非法,需用 sizeof(struct) 間接獲取。
  9. 函數類型不可用:sizeof(func) 非法,函數無存儲大小概念。

典型應用場景

  • 動態內存分配:malloc(n * sizeof(Type)) 避免硬編碼類型大小。
  • 結構體序列化/網絡傳輸:配合 #pragma pack(1) 計算線上大小,或使用 offsetof 手動布局。
  • 泛型宏/容器:#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0])) 僅適用於靜態數組作用域內。
  • 類型大小斷言:_Static_assert(sizeof(int) == 4, "int must be 32-bit");(C11)。
  • I/O 系統交互:fwrite(buf, sizeof(*buf), count, fp) 自動適配元素大小。

常見錯誤示例

// 錯誤:形參數組退化為指針
void foo(int arr[100]) {
    sizeof(arr); // 返回 4 或 8,而非 400
}

// 正確:傳遞長度或使用結構體包裹
void bar(int *arr, size_t len) { ... }
struct Wrapper { int data[100]; };
void baz(struct Wrapper w) { sizeof(w.data); // 400 }

總結:sizeof 是靜態類型系統的鏡像,正確理解其編譯期語義、對齊規則與退化例外,是編寫健壯、可移植 C 代碼的基礎功力之一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved