一、联合体
1.联合体的声明
联合体像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以拥有不同的类型。
联合体的引用方法是
union Un
{
char c;
int i;
}u;
//联合体的使用方法
u.i = 4
u.c = 'a'
2.联合体的特点
但联合体与结构体最大的不同就是联合体里的成员共用一块内存空间,且这块空间的大小至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
#include <stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un = {0};
//联合体空间的大小
printf("%d\n", sizeof(un));
// 下⾯输出的结果是⼀样的吗?
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
printf("%p\n", &un);
return 0;
}
输出结果:
4
001AF85C
001AF85C
001AF85C
由于是共用一块空间,当空间发生变化时,会影响到其他的成员,所以使用联合体的时候同时只能引用一个成员。例如以下代码
#include <stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un = {0};
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);
return 0;
}
输出结果:
11223355
当对un.i赋值后,空间就已经被占用了,此时再对un.c赋值,就会覆盖掉0x001AD85C原本的内容
3.联合体与结构体的比较
相同成员的结构体和联合体的内存布局如下图,我们可以清楚的看到由于联合体的特点,能有效节省一部分的内存空间。
struct S
{
char c;
int i;
};
struct S s = {0};
---------------------------------------------------------------------------------------------------
union Un
{
char c;
int i;
};
union Un un = {0};
4.联合体大小的计算
联合体的大小至少是最大成员的大小
当最大成员的大小不是最大对齐数的整数倍的时候就要扩大到最大对齐数的整数倍
#include <stdio.h>
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
int main()
{
//下⾯输出的结果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
return 0;
}
对于Un1:
char c[5]的大小为5个字节,对齐数为1;int i的大小为4个字节,对齐数为4;所以此时的Un1的大小为5个字节,最大对齐数为4,需要Un1的大小扩大到8个字节
对于Un2:
short c[7]的大小为14个字节,对齐数为2;int i的大小为4个字节,对齐数为4;所以此时Un2的大小为14个字节,最大对齐数为4,需要扩大到16个字节
5.联合的一个练习
写⼀个程序,判断当前机器是大端?还是小端?
union un
{
int i;
char c;
}un;
int main()
{
un.i = 1;
if (un.c == 1)
printf("小端");
else
printf("大端");
return 0;
}
假设为小端存储,则首地址处储存为01,若为大端存储,则首地址处储存为00,此时只需要看c的值是多少就能判断是大小端
二、枚举类型
1.枚举类型的声明
对于生活中可以一一列举的数据,如月份、性别、周几等,这些数据的表示就可以用到枚举类型
enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};
enum Color//颜⾊
{
RED = 2,//创建的时候对枚举常量赋值
GREEN = 4,
BLUE = 8
};
以上定义的 enum Day , enum Sex , enum Color 都是枚举类型
{}中的内容是枚举类型的可能取值,也叫枚举常量,枚举常量都是有值的,默认从0递增1,也可以在创建的时候进行赋值。枚举常量其实就是给了名字的整型
由于枚举常量就是整型,所以可以通过枚举常量对int类型的变量赋值,例如
enum Color//颜⾊
{
RED = 2,
GREEN = 4,
BLUE = 8
};
int main()
{
int a = RED;
printf("%d", a);//输出结果为2
}
2.枚举类型的使用
用枚举类型创建的变量叫做枚举变量,枚举变量和结构体变量以及联合体变量不同。枚举变量与int类型的变量很相似,未初始化的时候值为随机值,所占空间大小也为4,但是枚举变量的赋值只能用枚举常量
enum Color//颜⾊
{
RED=1,
GREEN=2,
BLUE=4
};
enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值
3.枚举类型的优点
我们可以使⽤ #define 定义常量,为什么⾮要使⽤枚举?
枚举的优点:
- 增加代码的可读性和可维护性
- 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
- 便于调试,预处理阶段会删除 #define 定义的符号
- 使⽤⽅便,⼀次可以定义多个常量
- 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤