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

C語言聯合體深度解析:定義、使用與內存佈局

     編輯:C 語言基礎

什麼是聯合體

聯合體(union)是一種構造類型,允許在同一塊內存空間中存儲不同類型的數據——但同一時刻只能存儲其中一種。這與結構體(所有成員並存)本質不同:結構體長度 = 成員長度之和(含對齊),聯合體長度 = 最長成員的長度。

聯合體定義語法

union UnionName {
    type1 member1;
    type2 member2;
    // ...
};

示例:教師/學生通用的「部門」字段

union Dept {
    int classNo;      // 學生:班級號
    char office[20];  // 教師:教研室名
};

聯合體變量聲明三種方式

// 1. 先定義後聲明
union Dept { int classNo; char office[20]; };
union Dept a, b;

// 2. 定義同時聲明
union Dept { int classNo; char office[20]; } a, b;

// 3. 匿名聯合體直接聲明
union { int classNo; char office[20]; } a, b;

成員訪問與賦值規則

  • 只能通過 變量.成員 或 指針->成員 訪問單一成員。
  • 不可對整個聯合體變量直接賦值或初始化(C 標準禁止)。
  • 賦值新成員會覆蓋舊成員的內存位模式,舊數據失效。

完整示例:教師/學生信息錄入與顯示

#include <stdio.h>
#include <string.h>

int main() {
    struct Person {
        char name[20];
        int age;
        char job;           // 's' 學生, 't' 教師
        union {
            int classNo;
            char office[20];
        } dept;
    } people[2];

    for (int i = 0; i < 2; ++i) {
        printf("輸入姓名 年齡 身份(s/t):");
        scanf("%s %d %c", people[i].name, &people[i].age, &people[i].job);

        if (people[i].job == 's') {
            printf("輸入班級號:");
            scanf("%d", &people[i].dept.classNo);   // 數組名/字符串不需 &,但這裡是 int
        } else {
            printf("輸入教研室:");
            scanf("%s", people[i].dept.office);     // office 是數組,自動退化為指針
        }
    }

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

內存佈局圖解

union Dept { int classNo; char office[20]; };  // 假設 int 4 字節,office 20 字節

變量 a 內存佈局(共 20 字節):
+--------------------+--------------------+--------------------+--------------------+
| office[0]          | office[1]          | ...                | office[19]         |  <-- 20 字節
+--------------------+--------------------+--------------------+--------------------+
| classNo (4 bytes)  | (padding 16 bytes) |                    |                    |  <-- 同一地址起始
+--------------------+--------------------+--------------------+--------------------+

賦值 a.classNo = 101 時:前 4 字節寫入 0x00000065,後 16 字節保持不變(殘留數據)。
賦值 strcpy(a.office, "CS Dept") 時:前 8 字節寫入字符串,覆蓋 classNo 位模式。

聯合體 vs 結構體 對比表

特性結構體 struct聯合體 union
成員存儲各自獨立內存,同時存在共享同一內存,互斥存在
總長度成員長度之和(含對齊填充)最長成員長度(對齊後)
初始化可整體初始化(C99 指定初始化器)標準禁止整體初始化,只能賦值單一成員
典型用途固定結構的記錄(學生、產品)變體記錄、協議數據帧、類型懲罰

進階:嵌套與指針

  • 結構體可嵌套聯合體(如上例),聯合體也可嵌套結構體。
  • 可聲明指向聯合體的指針:union Dept *p = &a;,通過 p->classNo 訪問。
  • 限制:聯合體變量不能作為函數參數整體傳遞,也不能作為函數返回值(ANSI C 規定)。但可傳遞指針或使用聯合體數組。

總結

聯合體是 C 語言實現「變體記錄」與「類型懲罰」的核心機制。理解其共享內存、互斥存儲、長度取最大三大特性,能幫你在嵌入式協議解析、節省內存的異構數據存儲等場景寫出高效、優雅的代碼。

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