共用體與結構體語法相似,但核心機制截然不同:結構體成員各自佔用獨立記憶體,而共用體所有成員共用同一塊記憶體空間,修改任一成員會影響其餘所有成員。
union 共用體名 {
成員列表
};
union data {
int n;
char ch;
double f;
};
// 三種建立變數方式
union data a, b, c; // 先定義再宣告
union data { int n; char ch; } a, b, c; // 定義同時宣告
union { int n; char ch; } a, b, c; // 匿名共用體直接宣告
#include <stdio.h>
union data {
int n;
char ch;
short m;
};
int main() {
union data a;
printf("%d, %d\n", sizeof(a), sizeof(union data)); // 4, 4
a.n = 0x40;
printf("%X, %c, %hX\n", a.n, a.ch, a.m); // 40, @, 40
a.ch = '9'; // ASCII 0x39
printf("%X, %c, %hX\n", a.n, a.ch, a.m); // 39, 9, 39
a.m = 0x2059;
printf("%X, %c, %hX\n", a.n, a.ch, a.m); // 2059, Y, 2059
a.n = 0x3E25AD54;
printf("%X, %c, %hX\n", a.n, a.ch, a.m); // 3E25AD54, T, AD54
return 0;
}
所有成員從記憶體起始位置對齊。修改 ch 影響第 1 位元組,修改 m 影響前 2 位元組,修改 n 影響全部 4 位元組。
不同架構(如 x86 小端、部分單片機大端)下,成員在記憶體中的具體分布順序不同,詳細機制請參閱「大端小端」專題。
學生需記錄分數,教師需記錄授課科目,前四欄相同。利用共用體節省空間:
#include <stdio.h>
#include <stdlib.h>
#define TOTAL 4
struct {
char name[20];
int num;
char sex;
char profession; // 's' 學生, 't' 教師
union {
float score;
char course[20];
} sc;
} bodys[TOTAL];
int main() {
int i;
for (i = 0; i < TOTAL; i++) {
printf("Input info: ");
scanf("%s %d %c %c", bodys[i].name, &bodys[i].num, &bodys[i].sex, &bodys[i].profession);
if (bodys[i].profession == 's')
scanf("%f", &bodys[i].sc.score);
else
scanf("%s", bodys[i].sc.course);
fflush(stdin);
}
printf("\nName\t\tNum\tSex\tProfession\tScore / Course\n");
for (i = 0; i < TOTAL; i++) {
if (bodys[i].profession == 's')
printf("%s\t%d\t%c\t%c\t\t%f\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.score);
else
printf("%s\t%d\t%c\t%c\t\t%s\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.course);
}
return 0;
}
共用體在嵌入式系統、通訊協定解析、型別轉換等場景極為實用。