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

C語言結構體記憶體對齊規則與偏移量計算完整指南

     編輯:關於C

對齊核心規則

  1. 成員偏移量: 每個成員相對結構體首址的偏移量必須是該成員大小的整數倍(編譯器自動插入填充位元組)。
  2. 結構體總大小: 必須是結構體中最大基本型別成員大小的整數倍(末尾可能填充)。
  3. 首址對齊: 結構體變數本身地址滿足最大成員對齊要求。

實例分析

struct A {
    unsigned short a;  // 2 bytes, offset 0
    unsigned int b;    // 4 bytes, offset 4 (填充 2 bytes)
    unsigned char c;   // 1 byte,  offset 8
};                     // 最大成員 4 bytes,總大小對齊到 12 bytes

sizeof(struct A) == 12(非 7)。成員 c 實際佔用 4 bytes 空間(含 3 bytes 填充)。

成員順序影響大小

struct B { char c; int i; short s; };  // 1 + 3填充 + 4 + 2 + 2填充 = 12
struct C { int i; short s; char c; };   // 4 + 2 + 1 + 1填充 = 8  (更緊湊)

優化技巧: 成員按大小遞減排列(大→小)可最小化填充。

偏移量計算巨集 offsetof

#include <stddef.h>  // 標準庫已提供
// 手動實現原理:
#define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE*)0)->MEMBER))
// 解析:(TYPE*)0 → 首址為 0 的結構體指標
// ->MEMBER → 取該成員(位址即偏移量)
// & → 取位址 → size_t 強轉

結構體初始化三種方式

struct A { int a; short b; char c; };

// 1. 指定成員初始化 (C99 designated initializers)
struct A a1 = { .a = 1, .b = 2, .c = 3 };

// 2. 順序初始化
struct A a2 = { 1, 2, 3 };

// 3. 逐個賦值
struct A a3; a3.a = 1; a3.b = 2; a3.c = 3;

位元域特殊對齊

struct Flags {
    unsigned int f1 : 1;
    unsigned int f2 : 3;
    unsigned int : 0;  // 強制下一位元域對齊到下一個 int
    unsigned int f3 : 4;
};

:0 強制對齊邊界,跨平台行為一致性較好。

pragma pack 控制對齊

#pragma pack(push, 1)  // 1 字節對齊(無填充)
struct Packed { char c; int i; };  // sizeof = 5
#pragma pack(pop)
// 注意:可能導致非對齊存取效能下降或硬體異常(某些架構)

工程建議

  • 網路協議/檔案格式結構體:使用 #pragma pack(1) + 手動處理字節序,或定義序列化/反序列化函式避免對齊差異。
  • 高效能資料結構:按大小排序成員、使用位元域壓縮旗標、考慮 alignas (C11) 顯式對齊關鍵熱點資料到快取行(64 bytes)。
  • 除錯技巧:printf("offset %s = %zu\n", #m, offsetof(T, m)) 列印所有成員偏移驗證預期。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved