联合体像结构体一样,联合体也是由一个或者多个成员构成,这些成员可以为不同的类型。但是在内存分配时,编译器只会为最大的成员分配足够的空间,联合体的特点是所有成员公用一块内存空间。联合体也叫共用体。
既然联合体的成员公用一个内存空间,那么当一个成员的值变化时,其他成员的值也跟着变化。
如上图所示,计算出来的联合体的大小为4个字节,刚好为 i 的内存大小,且联合体中 c 和 i 的地址相同,说明共用一块空间。
如上图所示,当我们修改 c 的值时,打印出来的 i 值也发生了相应的改变。
联合体计算大小有两个点:1.联合体的大小至少是最大成员的大小。2.当最大成员大小不是最大对齐数的整数倍时,就需要对齐到最大对齐数的整数倍处。
其实在联合体中也有最大对齐数的概念,与结构体最大对齐数的概念相同。
如上图所示,我们计算出来的两个内存大小都是8,在uu1和uu2中,最大对齐数都是4,而原始分配的空间都大于4,所以在最后的内存分配中,需要对联合体进行对齐。
在平常的使用中,基本很少用到联合体,但是在某些情况下,我们也可以应用联合体。如:当我们要做出一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。对于这三种商品都有:库存量、价格、商品类型相关的其他信息。
如果在平时的使用中,我们可能就根据不同的商品类型设计不同的结构体类型,但是因为其中存在相同的信息,所以我们也可以用联合体来节省空间,如下:
struct gift_list {
int stocknums;//库存量
double price;//价格
int itemtype;//商品类型
union {
struct {
char title[20];//书名
char author[20];//作者
int pagenums;//页数
}book;
struct {
char design[30];//设计,存储风格
int size;//大小
}cup;
struct {
char design[30];
int coloe;//颜色
int size;//尺寸
}shirt;
};
};
如上图代码,我们将共有的类型的信息设计在结构体中,将不同的结构信息设计在联合体中,联合体只需要分配处最大空间即可。
用联合体计算出当前编译器是大端存储还是小端存储:
#include
typedef union Sys {
int i;
char c;
}sys;
int main() {
union Sys Un = { 0 };
Un.i = 1;
if (Un.c == 0) {
printf("大端\n");
}
else {
printf("小端\n");
}
return 0;
}
测试结果:
枚举类型其实就是列举类型,将需要的变量提前列举出来。
比如:一周的天数:周一、周二……周末,可以意义列举;
性别:男、女、保密;
月份:1~12个月也可以一一列举……
如下:
enum Days {
Monday,
Tuesday,
Wendesday,
Thursday,
Friday,
Saturday,
Sunday
};
enum Sex {
MALE,
FEMALE,
SECRET
};
enum Threeprimarycolors {
RED,
BULE,
GREEN
};
enum Days,enum Sex为枚举类型,{}中的内容为枚举类型的可能取值,也叫枚举常量。对于枚举常量,都是有值的,默认从0开始,依次递增1。如下:
如上图,我们分别打印出这三个枚举类型中枚举变量的值,对于没有做出任何修改的enum Days,打印出枚举常量的值,从0开始依次递增,将enum Sex的第一个变量修改为5,则之后的变量值也依次递增,对于enum Threeprimarycolors,将每个枚举变量分别赋值,得出的值也是赋值上去的,没有什么区别。
与枚举相对应的为#define,我们也可以用#define来进行赋值,为什么需要使用枚举呢?
1.枚举可以增加代码的可读性与可维护性;
2.和#define定义的标识符⽐较枚举有类型检查,更加严谨;
3.便于调试,预处理阶段会删除 #define 定义的符号(调试时,只能看到对应的值,不能看到定义类型)
4.使⽤⽅便,⼀次可以定义多个常量
5.枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤,#define则是全局定义。