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

C語言聯合體與枚舉(五):聯合體定義、內存佈局、類型別名 typedef

     編輯:C 語言基礎

聯合體定義與聲明


union Tag {
    type1 mem1;
    type2 mem2;
    // ...
};
  • 成員共享同一塊內存,同一時刻只能存儲一個成員的值。
  • 聯合體大小 = 最大成員大小(按對齊向上取整)。

聲明三種方式(同結構體)


// 1. 先定義後聲明
union Data { int i; float f; };
union Data a, b;

// 2. 定義同時聲明
union Data { int i; float f; } a, b;

// 3. 匿名聯合體
union { int i; float f; } a, b;

聯合體內存佈局圖解


union Data {
    int i;        // 4 字節
    float f;      // 4 字節
    char c[10];   // 10 字節 -> 最大
};
// sizeof(union Data) == 10 (假設無額外對齊填充)

// 內存視圖 (10 字節):
// +----+----+----+----+----+----+----+----+----+----+
// | c[0] | c[1] | c[2] | c[3] | c[4] | c[5] | c[6] | c[7] | c[8] | c[9] |
// +----+----+----+----+----+----+----+----+----+----+
// | i (4 bytes) | (padding 6 bytes)                   |
// +----+----+----+----+----+----+----+----+----+----+
// | f (4 bytes) | (padding 6 bytes)                   |
// +----+----+----+----+----+----+----+----+----+----+

// 賦值 a.i = 0x12345678 -> 前 4 字節寫入 78 56 34 12 (小端)
// 賦值 a.f = 3.14      -> 前 4 字節覆蓋為浮點數位模式
// 賦值 strcpy(a.c, "Hi") -> 前 3 字節覆蓋 'H','i','\0'

成員訪問與賦值規則

  • 只能訪問單一成員:a.i、a.f、a.c。
  • 不可 整體賦值/初始化(標準禁止)。
  • 賦值新成員覆蓋舊位模式,舊數據失效。
  • 指針訪問:union Data *p = &a; p->i = 10;。

實戰:教師/學生通用「部門」字段


struct Person {
    char name[20];
    int age;
    char job;  // 's' 學生, 't' 教師
    union {
        int classNo;     // 學生:班級號
        char office[20]; // 教師:教研室
    } dept;
};

int main() {
    struct Person p[2];
    for (int i=0; i<2; ++i) {
        scanf("%s %d %c", p[i].name, &p[i].age, &p[i].job);
        if (p[i].job == 's')
            scanf("%d", &p[i].dept.classNo);
        else
            scanf("%s", p[i].dept.office);
    }
    for (int i=0; i<2; ++i) {
        if (p[i].job == 's')
            printf("%s %d %c %d\n", p[i].name, p[i].age, p[i].job, p[i].dept.classNo);
        else
            printf("%s %d %c %s\n", p[i].name, p[i].age, p[i].job, p[i].dept.office);
    }
    return 0;
}

注意:scanf("%s", p[i].dept.office) 中 office 是數組,自動退化為指針,不需 &。

結構體 vs 聯合體 對比

特性結構體 struct聯合體 union
成員存儲並存,各自獨立內存互斥,共享內存
大小成員大小之和 (+對齊)最大成員大小 (+對齊)
初始化支持整體/指定初始化標準禁止整體初始化
典型場景固定記錄變體記錄、省內存

嵌套與進階

  • 結構體可嵌套聯合體(如上例),聯合體可嵌套結構體。
  • 聯合體不能 作為函數參數整體傳遞,不能 作為函數返回值(ANSI C)。但可傳指針、用聯合體數組。

typedef:類型別名機制


typedef 原類型 新類型名;

核心優勢

  • 編譯期處理(宏是預處理文本替換),有類型語義、作用域、調試符號。
  • 簡化複雜聲明:typedef int (*FP)(int,int); FP fp;。
  • 增強可讀性:typedef uint32_t u32; u32 x;。
  • 可移植性:types.h 統一定義平台相關類型。

典型用法


// 基本類型
typedef unsigned char u8;
typedef unsigned long long u64;

// 數組
typedef char Name[32];
Name a, b;  // char a[32], b[32];

// 指針
typedef char *PStr;
PStr s1, s2;  // char *s1, *s2;

// 結構體
typedef struct { int x, y; } Point;
Point p1 = {1,2};

// 函數指針
typedef void (*Handler)(int);
Handler h = my_handler;

typedef vs #define 關鍵差異


typedef char *PSTR;
#define PSTR char *

const PSTR p1;  // char * const p1 (常量指針)
const PSTR p2;  // const char *p2 (指向常量的指針)  <-- 語義完全不同!

總結

  • 聯合體:共享內存、互斥存儲、大小取最大、變體記錄利器。
  • 結構體嵌套聯合體實現「同一字段不同類型」建模(如協議數據幀)。
  • typedef 編譯期類型別名,優於宏,簡化聲明、增強可讀、支援可移植。
  • 本章核心:結構/聯合/枚舉/位域/位運算/typedef — 構造類型與類型系統擴展完整體系。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved