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

C語言結構體記憶體對齊全解析:sizeof(struct) 面試必考點

     編輯:關於C語言

為何 sizeof(struct) ≠ 成員大小之和?

因為記憶體對齊。處理器訪問記憶體時,若資料跨越自然邊界(如 4-byte int 跨 4-byte boundary),需發起兩次總線事務並拼湊,嚴重損效能。編譯器自動插入填充位元組,確保每個成員起始位址滿足其對齊要求。

對齊三大鐵律

  1. 成員對齊:成員 offset % alignof(成員型別) == 0
  2. 結構體對齊:sizeof(struct) % max_align == 0(max_align 為所有成員中最大對齊數)
  3. 最小化原則:在滿足 1、2 前提下,sizeof 盡可能小

實戰演練:經典面試題

案例 1

struct A {
    char a;      // 1 byte
    short b;     // 2 bytes
    char c;      // 1 byte
    int d;       // 4 bytes
};

記憶體佈局 (32/64-bit 通用,假設 alignof(int)=4, alignof(short)=2)

成員offsetsize填充說明
a011下一個 short 需 2-byte 對齊,offset 1→2 需填 1
b220滿足 2-byte 對齊
c413下一個 int 需 4-byte 對齊,offset 5→8 填 3
d840滿足 4-byte 對齊
總計124sizeof(struct A) == 12

案例 2:成員重排省空間

struct B {       // 重新排序
    int d;       // 4
    short b;     // 2
    char a;      // 1
    char c;      // 1
};               // sizeof = 8 (無填充)

結論:將大對齊成員放前面、小對齊放後面,往往能減少填充,縮減結構體體積。

案例 3:巢狀結構體對齊

#pragma pack(8)          // 指定最大對齊 8
struct Inner {
    char a;              // align 1
    long b;              // align 4 (假設 long=4)
};                       // sizeof(Inner)=8 (max_align=4, 8%4=0)

struct Outer {
    char c;              // offset 0, align 1
    struct Inner in;     // offset 4 (需 4-byte 對齊), sizeof=8
    long long d;         // offset 16 (需 8-byte 對齊), sizeof=8
};                       // sizeof(Outer)=24

關鍵點:巢狀結構體視為「一個成員」,其對齊要求 = max(成員對齊, #pragma pack 值),但不超過自身 max_align。

#pragma pack(n) 精準控制

#pragma pack(push, 1)   // 保存舊值,設定 1-byte 對齊(緊湊模式)
struct Packed {
    char a;
    int b;
};                      // sizeof = 5 (無填充)
#pragma pack(pop)       // 恢復預設對齊
  • 用途:網路封包、檔案格式、硬體暫存器映射、共享記憶體協議
  • 代價:非對齊存取可能觸發 SIGBUS(ARM/SPARC)或顯著降速
  • 可移植替代:C11 _Alignas(1)、GCC/Clang __attribute__((packed))

驗證技巧:offsetof 宏

#include <stddef.h>
#include <stdio.h>

struct Demo { char a; int b; char c; };

int main(void) {
    printf("a: %zu\n", offsetof(struct Demo, a));  // 0
    printf("b: %zu\n", offsetof(struct Demo, b));  // 4
    printf("c: %zu\n", offsetof(struct Demo, c));  // 8
    printf("sizeof: %zu\n", sizeof(struct Demo));  // 12
    return 0;
}

位欄特殊規則

struct Flags {
    unsigned int f1 : 1;
    unsigned int f2 : 3;
    unsigned int : 0;    // 強制下一個位欄從新的儲存單元開始
    unsigned int f3 : 4;
};
  • 位欄不跨越儲存單元(通常是 unsigned int 或 _Alignas 指定型別)
  • :0 強制對齊到下一個單元邊界
  • 位欄順序(MSB/LSB)為實現定義,跨平台協議禁用位欄

總結速查表

場景對齊依據典型 sizeof
基本型別alignof(type) (通常等於 size)1,2,4,8,16
結構體max(成員對齊) 受 #pragma pack 限制按規則計算
聯合體max(成員對齊)max(成員 size) 向上對齊
陣列元素對齊元素 size * N (已對齊)

面試必背口訣

「成員各自對齊,結構整體對齊,填充最小化;
大型前排小型後,重排省空間;
pack 能改最大對齊,位欄不跨單元,跨平台慎用它。」

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