C语言零基础第19讲:自定义类型—联合体和枚举
目录
1.联合体
1.1 联合体类型的声明
1.2 联合体的特点
1.3 结构体和联合体对比
编辑
1.4 联合体大小的计算
1.5 联合体的练习
2.枚举
2.1 枚举的声明
2.2 枚举类型的优点
2.3 枚举类型的使用
正文开始
1.联合体
1.1 联合体类型的声明
联合体的关键字是union。
和结构体一样,联合体也是由一个或者多个成员构成的,这些成员可以是不同的类型。
我们来看一下声明的示例:
union Un
{char c;int i;
};
1.2 联合体的特点
对于联合体,编译器只为最大的成员分配足够的内存空间。
对于联合体,所有成员共用同一块内存空间,所以联合体也叫共同体。
所以一个联合体变量的大小,至少是最大成员的大小(因为联合体至少要有能力保存最大的那个成员)。
请看下面的代码:
如上,联合体的成员中,c为1个字节,i为4个字节。使用sizeof计算联合体变量的大小,得出的结果为4,可以印证,编译器只为最大的成员分配足够的内存空间。
我们将联合体变量,及其成员的地址打印出来,发现都是一样的。可以印证,所有的成员共用同一块内存空间。
因为联合体所有成员共用同一块内存空间,所以给其中一个成员赋值,其他成员的值也跟着变化。请看代码示例:
如上,结构体的大小为4个字节。首先给i赋值,4个字节中分别放着:44、33、22、11。然后再给c赋值,i的值也随之发生变化,内存中变为:55、33、22、11。
1.3 结构体和联合体对比
我们再对比一下,相同成员的结构体和联合体,它们的内存布局情况。
//结构体: //联合体:
struct S union Un
{ {char c; char c;int i; int i;
}; };
struct S s = {0}; union Un un = {0};
显然,使用联合体,是可以节省空间的。
1.4 联合体大小的计算
联合体的大小是怎么计算的呢?具体的规则如下:
- 联合体的大小,至少是最大成员的大小,但这并不意味着等于最大成员的大小。
- 不同的编译器,有不同的默认对齐数。VS中msvc默认为8,Linux中gcc没有默认对齐数,对齐数就是成员自身的大小。
- 联合体中的每个成员都对应着一个对齐数。
- 拿某成员自身的大小,去和默认对齐数作比较,谁更小,谁就是该成员对应的对齐数。
- 联合体的总大小,必须是最大对齐数的整数倍。
我们来看一个例子:
我们可以再做一个练习:
1.5 联合体的练习
题目:写一个程序,判断当前机器是大端还是小端字节序。
2.枚举
2.1 枚举的声明
枚举,顾名思义,就是把可能的取值列举出来。
比如,在我们的现实生活中,一周有7天,可以一一列举。月份有12个月,也可以一一列举。
我们来看一个举例:
上面定义的enum day就是一个枚举类型,{}中的内容是枚举类型的可能取值,也叫枚举常量。这些枚举常量,都是有值的,依次为:0,1,2,3...,请看示例:
对于枚举常量,我们在声明枚举类型的时候,也可以赋初值:
2.2 枚举类型的优点
如上,我们可以使用#define定义常量,为什么非要使用枚举呢?枚举到底有什么好?
我们来看一下枚举的优点:
- 增加代码的可读性和可维护性。
- 和#define定义的标识符相比,枚举有类型检查,更加严谨。
- 在调试阶段可以观察枚举变量,#define定义的符号不能被观察。
- 使用方便,一次可以定义多个常量。
- 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用。
2.3 枚举类型的使用
我们再来加深一下印象, 枚举类型的使用方式:
那么,是否可以拿整数来给枚举变量赋值呢?在C语言中是可以的,但是在C++中是不行的,C++的类型检查比较严格。
完结