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

C語言聯合體(union)詳解:共享內存、大小計算與類型安全模式

     編輯:關於C語言

聯合體核心特性

  • 共享內存:所有成員從同一地址開始,互斥共存(同一時刻僅一個成員有效值)。
  • 大小 = 最大成員大小:編譯器分配足夠容納最大成員的空間。
  • 修改一個影響所有:寫入任一成員會覆蓋共享內存,導致其他成員位模式改變。
  • 除共享特性外,語法與結構體一致(成員訪問、嵌套、數組等)。

大小計算驗證

union MyUnion {
    short n1;      // 2 bytes
    int n2;        // 4 bytes
    double n3;     // 8 bytes
};
printf("%u, %u\n", sizeof(union MyUnion), sizeof(double));  // 輸出 8, 8

共享內存行為演示

union MyUnion {
    unsigned char n1;      // 1 byte
    unsigned short n2;     // 2 bytes
    unsigned int n3;       // 4 bytes
} U = {0};

U.n2 = USHRT_MAX;  // 0xFFFF
// n1 = 0xFF (低位), n2 = 0xFFFF, n3 = 0x0000FFFF

U.n3 = UINT_MAX;   // 0xFFFFFFFF
// n1 = 0xFF, n2 = 0xFFFF, n3 = 0xFFFFFFFF

U.n1 = 0;          // 低位清零
// n1 = 0x00, n2 = 0xFF00, n3 = 0xFFFFFF00

直觀展示了小端序架構下低位優先佈局,以及成員間相互覆蓋效應。

進階應用:類型安全的異構數據容器

結合 enum 標識當前有效類型,實現「標籤聯合體」(Tagged Union / Discriminated Union),是 C 語言模擬代數數據類型的標準模式。

enum UnionType { SHORT, INT, FLOAT };

struct Rec {
    unsigned ID;
    enum UnionType type;  // 標識當前有效成員
    union {
        short s;
        int i;
        float f;
    } u;
} R[4];

// 賦值
R[0] = (struct Rec){1, SHORT, {.s = 123}};
R[1] = (struct Rec){2, INT,   {.i = 12345}};
R[2] = (struct Rec){3, FLOAT, {.f = 3.14}};
R[3] = (struct Rec){4, INT,   {.i = 54321}};

// 類型安全訪問
for (size_t i = 0; i < 4; i++) {
    switch (R[i].type) {
        case SHORT: printf("%u: %hd\n", R[i].ID, R[i].u.s); break;
        case INT:   printf("%u: %d\n", R[i].ID, R[i].u.i); break;
        case FLOAT: printf("%u: %g\n", R[i].ID, R[i].u.f); break;
    }
}

聯合體 vs 結構體對比

特性結構體 struct聯合體 union
內存佈局成員順序排列,互不重疊成員完全重疊,共享起始地址
大小≥ 所有成員大小之和(含對齊填充)= 最大成員大小(含對齊)
同時有效成員所有成員僅一個
典型用途聚合相關數據節省空間、類型懲罰、硬件寄存器映射

實務應用場景

  1. 節省內存:互斥使用的大數組/緩衝區共享空間。
  2. 類型懲罰:以不同類型解讀同一位模式(如 float 查看 int 位模式),需注意嚴格別名規則。
  3. 硬件寄存器:位域聯合體映射寄存器位結構。
  4. 網絡協議:同一消息頭部,不同負載類型。
  5. 標籤聯合體:實現變體類型(如上例),C 無原生變體類型的替代方案。

注意事項

  • 讀取非最後寫入的成員屬於未定義行為(C11 允許通過公共初始序列讀取,但一般情況下不可依賴)。
  • 對齊要求:聯合體地址需滿足所有成員對齊要求,大小為最大成員大小向對齊倍數調整。
  • 匿名聯合體(C11):結構體內直接聲明 union { ... };,成員可直接訪問 s.u → s.s。

總結

聯合體通過內存共享實現空間複用與類型重新解讀,是 C 語言底層編程的利器。配合標識枚舉構成標籤聯合體,可在保證類型安全前提下實現異構數據統一存儲,是系統級開發、嵌入式編程、協議解析的核心技術。

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