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

C 語言聯合體 深度解析:記憶體佈局、對齊規則與型別懲罰實戰

     編輯:關於C語言

一、聯合體定義與四大核心特性

《C Programming Language》定義:

  1. 聯合體是一個結構;
  2. 所有成員相對基地址偏移量為 0 (共享同一記憶體起始位置);
  3. 佔用空間足以容納最「寬」的成員;
  4. 對齊方式需滿足所有成員的對齊要求。

二、大小計算規則:不只是最大成員

union U1 { char s[9]; int n; double d; };  // sizeof = 16
union U2 { char s[5]; int n; double d; };  // sizeof = 8

規則:sizeof(union) = max( max_member_size, LCM(alignment_requirements) ) 向上取整到最大對齊值的倍數。

  • U1:最大成員 double (8) vs char[9] (9) → 至少 9。對齊需求:1, 4, 8 → LCM=8。9 非 8 倍數 → 擴至 16。
  • U2:最大成員 8,對齊 8,8 是 8 倍數 → 8。

三、記憶體佈局視覺化

union U { int i; float f; char c[4]; };
// 記憶體 4 bytes:
+----+----+----+----+
| i0 | i1 | i2 | i3 |  <- int i (4 bytes)
+----+----+----+----+
| f0 | f1 | f2 | f3 |  <- float f (同 4 bytes)
+----+----+----+----+
| c0 | c1 | c2 | c3 |  <- char c[4] (同 4 bytes)
+----+----+----+----+
所有成員起始位址相同 = 聯合體變數位址

四、型別懲罰與位模式重新解讀

聯合體合法用途:以一種型別寫入,以另一種型別讀取,檢查位模式。

union { float f; uint32_t u; } converter;
converter.f = 1.0f;
printf("0x%08X\n", converter.u); // 0x3F800000 (IEEE 754)

// 檢查端序
union { uint16_t s; char c[2]; } endian;
endian.s = 0x0102;
printf("%s\n", endian.c[0] == 1 ? "Big-Endian" : "Little-Endian");

五、標準規範與未定義行為邊界

六、實戰應用場景

1. 協議封包解析 (網路位序 ↔ 主機序)

union Packet {
    struct {
        uint16_t len;
        uint8_t  type;
        uint8_t  flags;
        uint32_t seq;
    } fields;
    uint8_t raw[8]; // 直接收發
};

2. 硬體暖存器映射

union Reg {
    uint32_t val;
    struct {
        uint32_t enable:1;
        uint32_t mode:3;
        uint32_t reserved:28;
    } bits;
};

3. 變長資料標記 (Tagged Union)

enum Type { INT, FLOAT, STR };
union Value { int i; float f; char *s; };

struct TaggedValue {
    enum Type type;
    union Value val;
};

4. 記憶體節省:互斥欄位

struct Event {
    enum { KEY, MOUSE, NET } kind;
    union {
        struct { int key; int mods; } key;
        struct { int x, y; int btn; } mouse;
        struct { int fd; char *buf; } net;
    } data;
};

七、匿名聯合體 (C11/GNU 擴展)

struct Sensor {
    int id;
    union {        // 無標籤,成員直接提升到結構體作用域
        float temp;
        int pressure;
        double humidity;
    };
};
// 存取: sensor.temp (而非 sensor.u.temp)

八、對齊屬性控制

// 強制 16 位元組對齊 (SSE/AVX)
union alignas(16) AlignedUnion { double d; char pad[16]; };

// 封裝對齊 (GCC/Clang)
union __attribute__((packed)) PackedUnion { char c; int i; }; // sizeof=5, 可能效能下降

九、總結

  • 聯合體 = 共享記憶體 + 型別懲罰合法通道。
  • 大小 = max(最大成員, 對齊值 LCM 向上取整)。
  • 嚴格別名規則下,聯合體是少數合法的型別懲罰方式。
  • 廣泛用於協議解析、硬體映射、標記聯合、記憶體緊湊結構。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
操作C99/C11備註
寫入成員 A,讀取成員 B (同類型大小)定義行為常見型別懲罰
寫入成員 A,讀取成員 B (不同大小)部分定義讀取共同部分定義,超出部分未指定值
寫入非最後存儲的成員未定義行為嚴格別名規則違反 (除非用 union)
透過指標強制轉型存取未定義行為違反嚴格別名,必須用 union 或 memcpy