对枚举、联合体进行介绍,包括枚举的声明、枚举的优点,联合体的声明、联合体的大小。
✨ 猪巴戒:个人主页✨
所属专栏:《C语言进阶》
跟着猪巴戒,一起学习C语言
目录
引言
枚举
枚举的优点
联合(共用体)
联合体的内存分布
如何通过联合体检验编译器的大小端?
联合体的大小
总结:
枚举变量的取值也是可以直接定义的。
enum Color//颜⾊
{
RED=2,
GREEN=4,
BLUE=8
};
通过定义宏,同样可以把各星期的取值打印出来。那枚举的优点是什么呢?
#define Mon 0
#define Tues 1
#define Wed 2
#define Thur 3
#define Fri 4
#define Sat 5
#define Sun 6
枚举的优点
2.和#define定义的标识符比较枚举有类型检查,更加严谨
枚举变量都具有类型,转换的时候会更加严格。
enum Day d = Fri;
enum Day d = 5; //在C++的语法中会报错
3.防止命名污染(封装)
enum将各枚举变量封装起来。
4.便于调试
在#define在预处理阶段,define所定义的标识符就已经被替换了,调试所看到的代码和所写代码会有所差异。
而枚举中变量是不会替换的。
联合是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间。
联合体的大小是联合体中成员的最大内存。
#include
union Un
{
int a;
char c;
};
int main()
{
union Un u;
printf("%d\n", sizeof(u));
printf("%p\n", &u);
printf("%p\n", &(u.a));
printf("%p\n", &(u.c));
return 0;
}
联合体的成员共用同一块内存空间,因此联合体的大小至少是最大成员的大小。
联合体的特点:
1.联合体成员的地址是一样的
2.联合体的大小至少为最大成员的大小
联合体的成员内存是重叠的,因此联合体在同一时刻,只能使用一个联合体成员。
通过下面的例子,理解联合体的内存分布:
例子1:
#include
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;
}
由于是小端操作系统,数据在内存在的储存为小端字节序。
绿色表示联合体成员 i 。
联合体的成员的地址是一样的,但是所占的字节不同。
红色表示的是联合体成员 c 。
一个数据 a = 0x11223344 在大小端字节序的不同排列
小端字节序储存:
大端字节序储存:
int a =0x11 22 33 44(这里用十六进制是为了表达)
代码:
#include
int check_sys()
{
union Un
{
char c;
int i;
}u;
u.i = 1;
return u.c;
}
int main()
{
int ret = check_sys();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
解释:
如果是小端字节序,i 在内存中是 01 00 00 00,这个时候将 c 拿出来,就是那联合体的第一个字节。如果是1,那么就是小端字节序。
如果是大端字节序,i 在内存中是 00 00 00 01,这个时候将 c 拿出来,就是那联合体的第一个字节。如果是0,那么就是大端字节序。
联合体的大小也存在对齐。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。
- VS 中默认的值为 8
- Linux中 gcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
例子1:
下面的打印结果是什么?
#include
union Un
{
char arr[5];
int i;
};
union Un2
{
short c[7];
int i;
};
int main()
{
printf("%d\n", sizeof(union Un));
printf("%d\n", sizeof(union Un2));
return 0;
}
Un的最大成员是 i ,4个字节的大小,arr[5]的内存如下,联合体Un的大小要对齐,对齐到4的整数倍,因此联合体Un的大小为8个字节。
Un2的最大成员是 i, 4个字节的大小,short[7]的内存如下,联合体Un2的大小要对齐,对齐到4的整数倍,因此联合体Un2的大小为16个字节。