联合体

和结构体类似,由一个或多个成员构成,这些成员可以是不同的类型

特点是所有成员共用一块内存空间,也叫共用体

给联合体其中一个成员赋值,其他成员的值也会发生变化

联合体的声明

1
2
3
4
5
6
7
8
union Un
{
char a; // 1
int x; // 4
};

union Un u = { 0 };
printf("%zd\n", sizeof(u));

联合体的特点

1
2
3
4
5
6
union Un u = { 0 };
printf("%zd\n", sizeof(u));
printf("%p\n", &u.a);
printf("%p\n", &u.x);
printf("%p\n", &u);

发现输出的地址都是一样的

再调试查看一次

1
2
3
4
union Un u = { 0 };
printf("x = %d\n", u.x);
u.a = 1;
printf("x = %d\n", u.x);

修改 a , x 也被改变了

联合体大小的计算

1
2
3
4
5
6
7
8
union Un
{
char c[5]; // 5 这里虽然是数组,但是是当作5个char 来处理的,所以这里确定对齐数是 1 < 8
int i; // 4
};

union Un u = { 0 };
printf("%zd\n", sizeof(u));

  • 联合体的大小至少是最大成员的大小

  • 联合体的大小也要是最大对齐数的整数倍


使用联合体是可以节省空间的

假设现在存在一个礼品兑换单,其中有三种商品书、杯子、衬衫,它们的属性如图

可以发现,三种商品有公共属性库存数量、商品类型、价格,分别再有专属属性

比如选中书时,使用的属性就有库存数量、商品类型、价格、书名、作者,尺寸、设

计、颜色就不需要使用

就可以将公共属性放到结构体当中,专属属性放在结构体再放在联合体当中,让这些

专属属性结构体共用一块内存空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
struct good_list1
{
int stock_number; // 库存数量
double price; // 价格
int item_type; // 商品类型

char title[20]; // 书名
char author[20]; // 作者
char design[30]; // 设计
int colors; // 颜色
int size; // 尺寸
};


struct good_list2
{
int stock_number; // 库存数量
double price; // 价格
int item_type; // 商品类型

union
{
// 使用联合体节省空间
// 使用一种商品时就只需要该商品的专属属性,不需要使用其他商品的专属属性
// 联合体开辟的空间比结构体少,也能完成需求
struct
{
char title[20]; // 书名
char author[20]; // 作者
}book;

struct
{
char design[30]; // 设计
int colors; // 颜色
int size; // 尺寸
}shirt;

struct
{
int colors; // 颜色
int size; // 尺寸
}cup;
};
};

printf("%zd\n", sizeof(struct good_list1));
printf("%zd\n", sizeof(struct good_list2));

可以看到节省了 1 / 3 的空间

使用联合体判断大小端字节序

因为联合体共用一块内存空间

1
2
3
4
5
6
7
8
9
10
11
12
13
int check_key()
{
union
{
// 用联合体判断大小端字节序
char a;
int i;
}check;
check.i = 1;
// 如果返回的是 1 , 就说明低位放在了低地址,就是小端
// 如果返回的是 0 , 就说明高位放在了低地址,就是大端
return check.a;
}

通过联合体也能判断大小端字节序