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

C 語言聯合體(Union)深度解析:記憶體共享機制與實戰應用

     編輯:關於C語言

核心概念:結構體 vs 聯合體

聯合體定義語法

union 聯合體名 {
    型別 成員1;
    型別 成員2;
    // ...
};

範例:人員資料(教師/學生互斥欄位)

union PerData {
    int class_id;      // 學生:班級編號
    char office[10];   // 教師:教研室名稱
};

變數宣告三種形式

/* 1. 先定義後宣告 */
union PerData { int class_id; char office[10]; };
union PerData a, b;

/* 2. 定義同時宣告 */
union PerData { int class_id; char office[10]; } a, b;

/* 3. 匿名聯合體直接宣告 */
union { int class_id; char office[10]; } a, b;

成員存取與初始化規則

  • 存取語法:變數名.成員名 或 指標->成員名
  • 禁止 對整個聯合體變數直接賦值(a = b 在 C 標準中未定義)
  • 禁止 宣告時初始化(union PerData u = {1}; 非標準)
  • 賦值只能針對單一成員進行

完整實戰範例:教師/學生通用表單

#include <stdio.h>

int main() {
    struct {
        char name[10];
        int age;
        char job;          // 's' = 學生, 't' = 教師
        union {
            int class_id;
            char office[10];
        } dept;
    } person[2];

    for (int i = 0; i < 2; i++) {
        printf("輸入: 姓名 年齡 身份(s/t) 班級/教研室: ");
        scanf("%s %d %c", person[i].name, &person[i].age, &person[i].job);
        
        if (person[i].job == 's')
            scanf("%d", &person[i].dept.class_id);   // 陣列/指標無需 &
        else
            scanf("%s", person[i].dept.office);      // 字串陣列名即地址
    }

    printf("\n%-10s %3s %3s %s\n", "姓名", "年齡", "身份", "班級/教研室");
    for (int i = 0; i < 2; i++) {
        if (person[i].job == 's')
            printf("%-10s %3d %3c %d\n", person[i].name, person[i].age, person[i].job, person[i].dept.class_id);
        else
            printf("%-10s %3d %3c %s\n", person[i].name, person[i].age, person[i].job, person[i].dept.office);
    }
    return 0;
}

進階特性與限制

匿名聯合體(C11 標準)

struct Widget {
    int type;
    union {      // 無標籤,成員直接提升到結構體作用域
        int i;
        float f;
        char *s;
    };
};
// 存取:w.i, w.f, w.s  (無需 w.u.i)

嵌套與對齊

  • 聯合體可嵌套結構體,結構體可嵌套聯合體
  • 大小遵循最大成員對齊:union { char c; double d; } 大小為 8 的倍數

函數參數與回傳限制

特性結構體聯合體
記憶體佈局成員依序排列,各自佔用獨立空間成員完全重疊,共享同一塊記憶體
總大小所有成員大小之和(含對齊填充)等於最大成員的大小(含對齊)
同時存活所有成員同時存在同一時刻僅一個成員有效
賦值行為各成員獨立賦值新值覆蓋舊值
操作結構體聯合體
值傳遞參數✅ 支援❌ C 標準不保證(建議用指標)
回傳值✅ 支援❌ 同上
指標傳遞✅✅ 推薦做法

記憶體佈局視覺化

union PerData { int class_id; char office[10]; };
假設 int=4 bytes, 對齊=4

記憶體位址:  基址  基址+1  基址+2  基址+3  基址+4 ... 基址+9
class_id 佔用: [  byte0  ][  byte1  ][  byte2  ][  byte3  ]
office   佔用: [  o  ][  f  ][  f  ][  i  ][  c  ][  e  ][\0][  ][  ][  ]
             ▲                                                       ▲
             同一塊記憶體區域(10 bytes,按最大成員對齊)              ▲

適用場景總結

  • 互斥資料欄位:同一實體不同型態下的不同屬性(如上例)
  • 型別轉換/位操作:union { float f; uint32_t u; } 觀察 IEEE 754 位模式
  • 硬體暫存器映射:嵌入式開發中,同一位址不同位域含義
  • 節省記憶體:大量物件中僅部分欄位同時生效

避坑提醒

  1. 寫入 class_id 後立即讀取 office → 未定義行為(垃圾資料)
  2. 依賴成員偏移量進行指標運算 → 違反嚴格別名規則,可能導致優化錯誤
  3. 跨平台傳輸聯合體資料 → 位元組序、對齊、型別大小差異導致解析錯誤
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved