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

C語言聯合體 union 詳解:共享內存、類型懲罰、协议解析實戰

     編輯:C 語言問答

union 本質:多變量共享同一塊內存

  • 大小 = 最大成員大小 (按最大對齊對齊)。
  • 同一時刻**只能存儲一個成員**的值,寫入新成員會覆蓋舊值。
  • 適用場景:節省內存、類型懲罰、協議解析、硬件寄存器映射。

語法與基本示例

union Data {
    int i;
    float f;
    char c[4];
};

union Data d;
d.i = 0x41424344;  // 写入整數
printf("i=0x%X, f=%f, c=%s\n", d.i, d.f, d.c);
// 輸出取決於端序:小端機 c="DCBA", f≈1.23e-10 (非預期值,演示覆蓋)

經典應用 1:節省內存 - 教師/學生通用表

struct Person {
    char name[20];
    int age;
    char type;          // 'T' 教師, 'S' 學生
    union {
        char dept[20];  // 教師:教研室
        int grade;      // 學生:年級
    } info;
};
// 結構體大小 = 20+4+1+max(20,4) + 對齊 ≈ 48 字節
// 若分開定義兩結構體數組,總內存翻倍

經典應用 2:類型懲罰 - 無需序列化庫的浮點/整數位模式互查

union FloatInt {
    float f;
    uint32_t u;
};

float f = 3.14159f;
union FloatInt fi = {.f = f};
printf("Float %f = 0x%08X (IEEE 754)\n", f, fi.u);
// 輸出: Float 3.141590 = 0x40490FDB

經典應用 3:網絡協議/文件格式解析 - 同一字節流多視圖

#pragma pack(1)
union Packet {
    uint8_t raw[12];
    struct {
        uint16_t magic;   // 0xA5A5
        uint8_t  version;
        uint8_t  type;
        uint32_t seq;
        uint32_t crc;
    } fields;
};
#pragma pack()

// 接收網絡數據
union Packet pkt;
recv(sock, pkt.raw, sizeof(pkt), 0);
// 直接訪問結構化字段
if (pkt.fields.magic == 0xA5A5) process(pkt.fields.type, pkt.fields.seq);

經典應用 4:硬件寄存器位域映射

union GPIO_REG {
    uint32_t word;
    struct {
        uint32_t MODE0  : 2;
        uint32_t MODE1  : 2;
        uint32_t MODE2  : 2;
        // ...
        uint32_t RESERVED : 18;
    } bits;
};

volatile union GPIO_REG *gpio = (void*)0x40020000;
gpio->bits.MODE0 = 1;  // 設置腳 0 為輸出
// 編譯器自動生成 讀-修改-寫 指令序列

關鍵注意事項

union vs struct 對比

struct S { int a; char b; };  // 大小 = 8 (對齊), 同時存 a 和 b
union U { int a; char b; };   // 大小 = 4, 同一時間只存 a 或 b

靈活運用 union,能在嵌入式、系統編程、高性能序列化中實現**零拷貝類型轉換**與**極致內存效率**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
陷阱說明對策
嚴格別名規則違反通過 union 讀取非最近寫入的成員屬實現定義行為 (C99 明確允許),但 C++ 不允許C 中放心用;C++ 用 memcpy 或 std::bit_cast (C++20)
端序依賴多字節成員 (int/float) 字節序與 CPU 一致,跨平台傳輸需統一網絡序收發端統一用 htonl/ntohl 或手動字節序轉換
對齊導致大小超預期union 大小按最大成員對齊,可能大於最大成員#pragma pack(1) 或 __attribute__((packed)) 壓緊
未初始化讀取讀取從未寫入的成員 → 不確定值始終先寫入再讀取,或靜態初始化 union U u = {0};