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

C/C++ sizeof 運算子全方位深度解析:從基本型別到類別佈局

     編輯:關於C語言

sizeof 是 C/C++ 核心運算子,編譯期計算型別或運算式的位元組大小,回傳 size_t。本文系統涵蓋基本型別、指標、陣列、結構體/類別對齊、虛函式表、空類別等進階主題,並對比 C/C++ 差異。

語法與基本特性

sizeof(type)      // 型別需括號
sizeof expr       // 運算式可無括號,不求值
sizeof var        // 變數可無括號
  • C: 僅編譯期計算 (C99 VLA 例外)。
  • C++: 樣板元編程中常用於型別特徵萃取。
  • 不求值特性:sizeof(func()) 不會呼叫 func(),只取回傳型別大小。

基本型別與指標

型別32位系統64位系統
char / signed char / unsigned char11
short22
int44
long48 (Linux) / 4 (Windows)
long long88
float / double / long double4 / 8 / 12-16同上
所有指標48

陣列與退化


int a[10];
sizeof(a);           // 40 (完整陣列大小)
sizeof(a[0]);        // 4 (單元素大小)
int *p = a;
sizeof(p);           // 4/8 (指標大小)
sizeof(*p);          // 4 (指向型別大小)

void func(int arr[10]) {
    sizeof(arr);     // 4/8 ! 參數退化為指標
}

結構體對齊鐵律 (C/C++ 共通)

三大準則:

  1. 結構體起始位址能被最寬基本成員大小整除。
  2. 每個成員相對起始位址的偏移量為其大小倍數 (編譯器插入內部填充)。
  3. 結構體總大小為最寬基本成員大小的倍數 (末尾填充)。

struct S1 { char c; int i; };     // 1 + 3填充 + 4 = 8
struct S2 { int i; char c; };     // 4 + 1 + 3填充 = 8
struct S3 { char c1; S1 s; char c2; }; // 1 + 3填充 + 8 + 1 + 3填充 = 16

工具:offsetof(S, member) 取得成員偏移量 (編譯期常數)。

C++ 類別大小進階

  • 非靜態資料成員:計入大小,遵循對齊規則。
  • 靜態資料成員:不計入,屬於類別而非物件。
  • 非虛函式 (含 static):不計入,屬於類別程式碼區。
  • 虛函式:引入 vptr (虛函式表指標),通常 +4/+8 位元組。
  • 虛繼承:引入 vbptr 或擴展 vptr,大小增加更複雜。
  • 空類別:大小為 1 (確保不同物件有唯一位址)。

class A { int a; float b; char c; };          // 12 (對齊)
class B { static int s; int a; };             // 4 (s不計入)
class C { virtual void f(); int a; };         // 8/16 (vptr + a + 填充)
class D : virtual public C { int d; };        // 複雜,含 vbptr

實用技巧與最佳實踐

  1. 陣列元素數:sizeof(arr)/sizeof(arr[0]) (僅適用非退化陣列)。
  2. 型別安全 malloc:p = malloc(n * sizeof(*p))。
  3. 編譯期斷言:static_assert(sizeof(T) == 16, "layout changed");。
  4. 壓縮對齊:#pragma pack(1) 或 `__attribute__((packed))`,慎用 (可能降低存取效能、觸發硬體異常)。
  5. 跨平台序列化:勿直接傳輸結構體記憶體,必須逐欄位編碼 (處理端序、對齊、型別大小差異)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved