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

C 語言聯合體 完整解析:記憶體佈局、初始化限制與類型轉換技巧

     編輯:關於C語言

核心特性

  1. 共享記憶體:聯合體所有成員從相同位址開始,sizeof(union) 等於最大成員大小 (對齊後)。
  2. 單一活躍成員:同一時間只能安全存取最近寫入的成員;讀取非活躍成員屬於未定義行為 (C11 允許型別檢視的特定情況)。
  3. 位址相同:&union_var == &union_var.member1 == &union_var.member2。

語法限制 (C89/C99)

  • ❌ 無法直接初始化聯合體變數 (C99 允許指定初始化器:union U u = { .member = value };)
  • ❌ 無法對整個聯合體賦值 (需逐成員複製或 memcpy)
  • ❌ 無法直接作為函數參數/回傳值傳遞 (但可包裝在結構體中傳遞)
  • ❌ 無法取址後轉型存取非活躍成員 (嚴格別名規則)

實用技巧:型別重新解讀 (Type Punning)

雖然標準限制嚴格,但在實際系統程式 (驅動程式、網路協定解析、序列化) 中常見以下模式:

範例:double 與 byte 陣列互轉

union {
    char bytes[8];
    double value;
} converter;

converter.value = 3.1415926535;
for (int i = 0; i < 8; i++) {
    printf("Byte %d: 0x%02X\n", i, (unsigned char)converter.bytes[i]);
}
// 輸出 IEEE 754 雙精度浮點數的位元模式

網路封包解析實例

union Packet {
    struct {
        uint16_t magic;
        uint16_t version;
        uint32_t payload_len;
        uint8_t  payload[0];  // 柔性陣列成員 (C99)
    } fields;
    uint8_t raw[1024];  // 原始位元組緩衝區
};

void parse_packet(const uint8_t *data, size_t len) {
    union Packet pkt;
    memcpy(&pkt, data, len);  // 安全複製
    printf("Magic: 0x%04X, Ver: %d, Len: %u\n",
           ntohs(pkt.fields.magic),
           ntohs(pkt.fields.version),
           ntohl(pkt.fields.payload_len));
}

對齊與大小計算範例

union Example {
    char   c;       // 1 byte
    short  s;       // 2 bytes, align 2
    int    i;       // 4 bytes, align 4
    double d;       // 8 bytes, align 8
};
// sizeof(Example) == 8 (最大成員 double 對齊至 8)
// 位址偏移:c=0, s=0, i=0, d=0 (全從 0 開始)

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

struct Message {
    uint32_t type;
    union {
        struct { int x, y; } mouse;
        struct { int key; } keyboard;
        struct { float x, y, z; } sensor;
    };  // 無標籤,成員直接提升到 struct 範疇
};

// 使用
struct Message msg;
msg.type = MSG_MOUSE;
msg.mouse.x = 100;  // 直接存取,無需 .union_tag

總結:何時使用聯合體

適用場景不適用場景
硬體暖存器映射、協定封包解析需要同時保存多種類型值
節省記憶體的互斥欄位 (如符號表)跨執行緒共享且無同步機制
型別安全的位元操作替代方案依賴特定記憶體佈局的可移植程式
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved