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

VC++ 結構體記憶體對齊深度解析:為什麼 sizeof 不等於成員大小總和

     編輯:VC 教學

前言

C/C++ 結構體大小不單純等於成員大小總和,編譯器為了存取效率會依照對齊規則插入填補位元組。VC++(MSVC)預設採用「成員對齊到其大小,整體結構對齊到最大成員大小」的規則。本文透過實例詳細推導計算過程。

VC++ 基本型別大小(32 位元)

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

對齊規則

  1. 第一個成員偏移量為 0。
  2. 後續成員偏移量必須是「該成員大小」的倍數(不超過編譯器封裝大小,預設 8)。
  3. 結構體總大小必須是「最大成員對齊需求」的倍數(尾端填補)。
  4. 可用 #pragma pack(n) 改變封裝大小(1,2,4,8,16)。

實例逐步推導

案例 1:char + long

struct A { char c; long l; };
// 佈局:
// offset 0: c (1 byte)
// offset 1-3: padding (3 bytes) → 使 l 對齊到 4
// offset 4: l (4 bytes)
// 總計 8 bytes

sizeof(A) == 8

案例 2:char + long + short

struct B { char c; long l; short s; };
// offset 0: c (1)
// offset 1-3: pad (3)
// offset 4: l (4)
// offset 8: s (2)
// offset 10-11: tail pad (2) → 結構對齊到 4 的倍數 (12)

sizeof(B) == 12

案例 3:調整順序 char + short + long

struct C { char c; short s; long l; };
// offset 0: c (1)
// offset 1: pad (1) → s 對齊 2
// offset 2: s (2)
// offset 4: l (4)
// 總計 8 bytes(無尾端填補)

sizeof(C) == 8 — 成員順序影響大小!

複雜範例完整計算

範例 1

struct Data1 {
    int i;      // 4 @0
    char ch;    // 1 @4
    double d;   // 8 @8 (需對齊 8,故 ch 後填補 3)
    short s;    // 2 @16
    float f;    // 4 @18 → 對齊 4 需填補 2 → @20
    long l;     // 4 @24
};
// 總計 28 → 尾端對齊 8 → 32

sizeof(Data1) = 32

範例 2

struct Data2 {
    short s1;  // 2 @0
    char ch1;  // 1 @2
    short s2;  // 2 @4 (ch1 後填補 1)
    char ch2;  // 1 @6
};
// 尾端對齊 2 → 8

sizeof(Data2) = 8

範例 3

struct Data3 {
    int i;     // 4 @0
    char ch1;  // 1 @4
    short s2;  // 2 @6 (ch1 後填補 1)
    char ch2;  // 1 @8
};
// 尾端對齊 4 → 12

sizeof(Data3) = 12

控制對齊:#pragma pack


#pragma pack(push, 1)  // 1 位元組封裝,無填補
struct Packed { char c; long l; };
#pragma pack(pop)
sizeof(Packed) == 5;  // 但存取 long 可能觸發對齊錯誤或效能下降

最佳實務建議

  • **依大小遞減排序成員**(大型別在前),可最小化填補。
  • **避免不必要的 #pragma pack(1)**,除非需與硬體/網路協定精確對應。
  • **使用 offsetof 宏**驗證成員偏移:offsetof(Data1, d) 應為 8。
  • **64 位元編譯**時指標變 8 位元組,對齊需求變 8,結構體大小通常會膨脹。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved