C语言之联合和枚举
文章目录
- C语言之联合和枚举
- 1. 联合体
- 1.1 联合体的声明
- 1.2 联合体的特点
- 1.3 结构体和联合体对比
- 1.4 联合体大小的计算
- 1.5 联合体小练习
- 2. 枚举
- 2.1 枚举类型的声明
- 2.2 枚举类型的优点
- 2.3 枚举类型的使用
1. 联合体
1.1 联合体的声明
像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体。
给联合体其中⼀个成员赋值,其他成员的值也跟着变化
1.2 联合体的特点
代码一:
#include <stdio.h>union U
{char a;int b;
};
int main()
{union U uu = { 0 };printf("%zd\n", sizeof(uu));return 0;
}
代码运行结果:>
4
结论:联合的成员是公用一块空间的,联合体变量的大小至少是最大成员的大小(至少确保能存下最大的那个成员)
代码二:
#include <stdio.h>union U
{char a;int b;
};
int main()
{union U uu = { 0 };printf("%p\n", &(uu.a));printf("%p\n", &(uu.b));printf("%p\n", &uu);return 0;
}
代码运行结果:>
012FFD90
012FFD90
012FFD90
可以看到无论是联合体的地址还是联合体成员的地址都是一样的,说明他们共用同一块空间
代码三:
#include <stdio.h>union U
{char a;int b;
};
int main()
{union U uu = { 0 };uu.b = 0x11223344;uu.a = 0x55;printf("%#x\n", uu.b);return 0;
}
%#x打印的是带0x的十六进制数,0x11223344是一个十六进制数
代码运行结果:>
0x11223355
由于是小端字节序存储,优先存低字节的也就是44,然后通过char修改了第一个字节的内容,将44修改成了55,所以打印结果为0x11223355
1.3 结构体和联合体对比
union U
{char a;int b;
};
struct S
{char a;int b;
};
相对于结构体,联合体较节省空间
1.4 联合体大小的计算
- • 联合体大小至少是联合体中最大成员的大小
- • 当最大成员的大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍,和结构体一样,联合体也是有对齐的
#include <stdio.h>union U1
{char a[7];int b;
};
union U2
{short a[7];int b;
};
int main()
{union U1 u = { 0 };union U2 uu = { 0 };printf("%zd\n", sizeof(u));printf("%zd\n", sizeof(uu));return 0;
}
代码运行结果如下:>
8
16
联合体U1中有两个成员,char a[7] int b 其中最大成员为char a[7],为7个字节,char为1字节,默认对齐数为8,取较小值1,int为4字节,默认对齐数为8,取较小值4,所以两个成员中的最大对齐数为4,最大成员的大小为7,不是最大对齐数4的倍数,所以将对齐至8字节,对齐之后才是联合体的大小
同理联合体U2,也有两个成员,最大成员的大小为14字节,不是最大对齐数4的倍数,所以将对齐至16字节,对齐之后才是联合体的大小
1.5 联合体小练习
要求:写一个代码,判断当前机器的字节序
代码一:
#include <stdio.h>int check_sys()
{int n = 1;return *(char*)&n;
}
int main()
{int ret = check_sys();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}
小端字节序,将低字节内容存到低地址,高字节内容存到高地址
大端字节序,将高字节内容存到低地址,低字节内容存到高地址
内存使用优先使用低地址
1的十六进制为00 00 00 01
小端字节序为 01 00 00 00
大端字节序为 00 00 00 01
取出1的地址,将其从int*类型的指针强制类型转化为char*类型的地址,这样解引用的时候就会访问低地址处的内容,如果解引用得到1则是小端,得到0则为大端
代码二:
使用联合体的方式
#include <stdio.h>int check_sys()
{union{char a;int b;}un;un.b = 1;return un.a;
}
int main()
{int ret = check_sys();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}
通过联合体公用同一块空间的方式,如果第一个字节中存的是1则是小端,如果存的是0则是大端
2. 枚举
2.1 枚举类型的声明
枚举顾名思义就是一一列举
enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
枚举类型:enum Day
枚举常量:Mon,Thus,… //枚举常量使用逗号隔开,最后一个常量不需要
枚举常量是有值的,第一个常量的值默认从0开始,依次递增1,也可以在声明的时候为枚举常量赋值
enum Color
{RED = 4,YELLOW = 8,BLUE = 12
};
2.2 枚举类型的优点
有#define关键字为什么还要使用枚举呢
- 增加代码的可读性和可维护性
- 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
- 便于调试,预处理阶段会删除 #define 定义的符号
- 使⽤⽅便,⼀次可以定义多个常量
- 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤
2.3 枚举类型的使用
#include <stdio.h>enum Color
{RED = 4,YELLOW = 8,BLUE = 12
};int main()
{enum Color clr = BLUE;//使用枚举常量为变量赋值return 0;
}
#include <stdio.h>enum Color
{RED = 4,YELLOW = 8,BLUE = 12
};int main()
{enum Color clr = 12;//使用整数为变量赋值,12 == BLUEreturn 0;
}
在C语言中,对其规定不是很严格,在C++中,C++的类型检查比较严格,这是个语法错误,无法使用整型对枚举变量赋值