目录
一、结构体
1.结构体的定义
2.结构体的自引用
3.结构体的初始化
4.结构体的内存对齐
二、枚举
1.枚举类型
2.枚举相较于define的优势
三、联合体
1.联合体的定义
2.联合体大小的计算
3.联合体的应用———大小端的判断
1-1.结构体的定义
结构体是c语言32个关键字的其中之一,结构体是不同类型数据的集合,这些类型称为结构体变量。
1-2结构体声明
由结构体关键字+结构体标签组成
例如描述一个学生就可以使用结构体。
除此方式外,结构体还有特殊的声明,成为结构体匿名类型
比如上述学生结构体关键字可以省略
1-3结构体的自引用
1-4结构体变量的定义和初始化
同时第一个结构体变量s为全局变量,第二个结构体变量s为局部变量。
1-5结构体的内存对齐
结构体的内存对齐一直是一大热点
那么结构体究竟是如何对齐呢?
先看上面两个例子:
如果 没有学过结构体的内存对齐应该是这样做的
我们都知道在32位中int类型是四个字节,char类型是一个字节,如果这样算的话sn1,sn2都是六个字节,那么结果究竟是多少呢,我们让代码运行一下,结果如下:
而最后的结果为8 12;
为什么一定要存在对齐呢?为什么不能像我们想的那样运行呢?主要有两个原因:
1.平台原因:
不是所有的平台都能访问任意地址的数据;
2.性能原因:
栈上的数据结构应该尽可能地去对齐,如果没有对齐的话,处理器需要对其进行两次访问,但是如果对齐的话,只需进行一次访问(减少了运行时间,提高效率)
知道了对齐的原因,我们就应该了解一下对齐的规则;
1.第一个成员永远对齐到结构体起始位置为0的偏移处
2.第二个成员要对齐到【某个对齐数】的整数倍的偏移处
对齐数:结构体成员自身的大小和默认对齐数的较小值;
vs默认偏移数为8;
lunix环境不设对齐数(对齐数是结构体成员自身的大小);
3结构体的总大小必须是最大对齐数的整数倍。每个结构体成员都有一个对齐数,其中最大的对齐数就是最大对齐数
4.如果有嵌套结构体的情况,嵌套的结构体对齐到自己最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍;
先分析sn1,假设起始位置0为如图所示位置,首先int是四个字节向后填充四个黄色(一格代表一个字节),而char的较小对齐数为1(char为1,默认对齐数为8,较小值为1)起始位置4是1的整数倍,结束时5也是对齐数1的整数倍,填充一格,而在最后偏移量停留在6,最大对齐数为4(4,1,1较大值为4),所以还得填充两格到偏移量为的位置,所以社sn1的大小为8;
sn2
sn2首先是char所以占一个字节,而后面int四个字节,所以必须从4的整数倍开始,所以首先从偏移量为4处开始,偏移量为8刚好结束,同理char又是一个字节,占一个字节,最后在偏移量为9处结束,偏移量结束必须是最大对齐数4的整数倍,所以在12处结束,所以sn2占12个字节
2-1枚举类型
枚举顾名思义就是列举,把枚举类型可能的值一一列举出来;
例如下图:
enum color就是枚举类型,而BLUE,GREEN,RED就是枚举常量,并且枚举常量的值都是从零开始,依次递增,当然也可以自己定义枚举常量的值;
同时也要注意!!
枚举常量最后一个值之前的值结尾都是逗号,最后一个结尾无任何符号;
同时也会有这样的疑问,这不是和#define的作用差不多嘛?什么情况下用#define,什么情况下用枚举呢?
大多数情况下用枚举比较好,有以下几点原因:
1.增加代码的可读性与可维护性;
2.和define定义的标识符比较枚举定义的标识符有类型检查更加严谨;
3.防止命名污染;
4.便于调试;
3-1联合体的定义:
联合体的成员共用同一块空间。
3-2联合体的特点
1.所有成员共用一块地址
2.联合体大小的计算:
(1).联合体的大小至少是最大成员的大小;
(2).当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍;
根据上面例子,int最小对齐数是4,char的最小对齐数是1,所以最大对齐数是4,联合体最大成员的大小是4,刚好是最大成员的整数倍;
3-3联合体的应用——大小端的判断
1.常规方法——强制类型转换
知识:1.大端:高位字节序存在低地址,地位字节序反之;
2.小端:低位字节序存在低地址,高位字节序反之;
2.联合体