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 是數組,自動退化為指針,不需 &。
| 特性 | 結構體 struct | 聯合體 union |
|---|---|---|
| 成員存儲 | 並存,各自獨立內存 | 互斥,共享內存 |
| 大小 | 成員大小之和 (+對齊) | 最大成員大小 (+對齊) |
| 初始化 | 支持整體/指定初始化 | 標準禁止整體初始化 |
| 典型場景 | 固定記錄 | 變體記錄、省內存 |
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 char *PSTR;
#define PSTR char *
const PSTR p1; // char * const p1 (常量指針)
const PSTR p2; // const char *p2 (指向常量的指針) <-- 語義完全不同!