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

C 語言聯合體 深度解析:記憶體佈局、大小計算與實戰應用

     編輯:C 語言入門

聯合體四大核心特性

  1. 結構本質:聯合體是一種特殊結構
  2. 零偏移:所有成員相對基址偏移量皆為 0
  3. 容納最寬:空間大小至少容納最大成員
  4. 對齊兼容:對齊方式需滿足所有成員需求

記憶體佈局視覺化

union U {
    char s[9];  // 9 bytes
    int n;      // 4 bytes
    double d;   // 8 bytes
};
// 所有成員起始位址相同
// 實際大小 = 16 bytes (非 9!)

大小計算規則

滿足兩條件:

  1. 大小 ≥ 最大成員大小
  2. 大小能被所有基本型別大小整除(1, 4, 8 → LCM = 8,但 9 不能被 8 整除 → 擴展至 16)

實測驗證程式碼

#include 
using namespace std;

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

int main() {
    U1 u1; U2 u2;
    printf("%d\n", sizeof(u1)); // 16
    printf("%d\n", sizeof(u2)); // 8

    // 驗證基址相同
    printf("0x%x\n", &u1);
    printf("0x%x\n", &u1.s);
    printf("0x%x\n", &u1.n);
    printf("0x%x\n", &u1.d); // 全部相同

    // 資料重疊實驗
    u1.n = 1; // 記憶體前4 bytes: 01 00 00 00
    printf("%d\n", u1.s[0]); // 1 (小端序)
    printf("%lf\n", u1.d);   // 0.000000 (解讀為 double)

    // 逐 byte 檢視
    unsigned char *p = (unsigned char *)&u1;
    for(int i=0;i<8;i++) printf("%d\n", *(p+i));
    // 輸出: 1,0,0,0, 48,204,64,0 (double 0.0 的記憶體模式)
    return 0;
}

關鍵現象解析

操作記憶體變化讀取其他成員結果
u.n = 1前 4 bytes = 01 00 00 00u.s[0] == 1, u.d ≈ 0
u.d = 1.08 bytes IEEE 754 模式u.n 變為解讀後的整數

實戰應用場景

1. 型別轉換

union { float f; uint32_t bits; } converter;
converter.f = 3.14f;
printf("0x%08X\n", converter.bits); // 0x4048F5C3

2. 通訊協定封包

union Packet {
    struct { uint16_t cmd; uint16_t len; char data[12]; } fields;
    char raw[16];
};

3. 省記憶體的互斥狀態

union State {
    struct { uint8_t flag; int value; } active;
    struct { uint8_t flag; char err_msg[16]; } error;
};

注意事項

  • 不可同時使用多個成員,寫入一個會破壞其他成員資料
  • 位元欄位 在聯合體中需特別小心編譯器實作差異
  • 對齊要求 可能導致實際大小超過預期(如本文 U1 從 9→16)
  • 嚴格別名規則:透過聯合體進行型別雙關在 C99/C11 屬未定義行為,C++ 則明確允許

圖片資源

程式碼分隔

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