目录:
一· 结构体
1.结构体类型声明
2.结构体自引用
3.结构体内存对齐
4.结构体传参
5.基于结构体实现的位段
二· 枚举
1.枚举类型定义
2.枚举优点
3.枚举的使用
三· 联合(共用体)
1.联合类型的定义
2.联合的优点
3.联合大小的计算
结语
WeChat_20240720200001
思维导图:
一· 结构体
1.结构体类型声明
1.1结构体的声明
结构体是一些值的集合。(注意不同于数组的定义)
数组:一组相同数据类型的集合
这些值称为成员变量。
结构体里面的每一个成员变量可以是不同的类型有可以是相同的类型。
1.2 结构体变量的创建
1.3对变量初始化
和数组初始化方式一样,都是用大括号来表示,只不过可以指定初始化的先后顺序
按成员变量声明先后顺序初始化
按指定顺序初始化
1.4匿名结构体
注意匿名结构体类型只能使用一次,也就是说在创建这个匿名结构体类型同时创建匿名结构体变量。
此时语句 struct *p = &s1;编译不通过。
虽然第5行和第12行代码创建的结构体都是一样的,但是在编译器看来是2个不同类型的匿名结构体
2.结构体自引用
思考以下的问题:
在一个结构体里面包含一个成员和自己类型一样的结构体是否支持???
显然是不支持的。
对于这个问题的理解,可以举个栗子:
比如说把 struct Node 视为一个房子,这个房子里面放的有一个data 大小的一个物体,再放一个和struct Node大小一样的房子。你认为可以放的下?
一样的道理:next 这个结构体变量里面依然是有2个成员:data ,struct Node next ;依次循环下去,这个struct Node 大小到底是多少,是未知的。
正确处理:
改写为一个结构体类型指针(大小无非就是4/8个字节)。
3.结构体内存对齐
3.1内存对齐规则:
3.2 关于结构体大小的计算
1)
2)
3)内嵌结构体
** 运行结果:**
3.3为什么存在结构体内存对齐
1)平台原因:
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2)效率:
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访
问。
总而言之:结构体内存对齐是以空间换时间的思想。
3.4 修改默认对齐数
使用到了 **#pragma pack ** 这个命令
当我们把对齐数修改为1的时候,也就意味着不存在内存对齐这个规则了。换言之:修改之后的对齐数不能是随意更改的,要符合实际的意义。
4.结构体传参
5.基于结构体实现的位段
5.1位段的定义
位段的声明和结构体声明是类似的,但是也有不同的地方
1)位段成员的类型必须是int ,unsigned int ,signed int ,char
2)位段的成员名字后有一个冒号和一个数字
5.2位段大小的求解
1)位段成员类型必须是 int ,unsigned int ,signed int ,char
2)位段在空间上是以4个字节或者1个字节的方式来开辟的
3)位段有很多不确定的因素,所以位段是不支持跨平台的
分析见下:
运行结果:
接下来就需要我们再进一步研究一下,到底在内存里面是从左往右还是从右往左开始存储???
通过对内存里面的数据进行分析,得知,数据是自右向左开始存储的
但是当我我们进入调试阶段,打开监视窗口的时候,发现,此时a,,b,c,d的数据已经 发生了变化
这是为啥???
分析见下:
二· 枚举
1.枚举类型定义
枚举其实就是把可能的数值进行一 一例举
比如说:
一周有7天:周一,周二,周三 ,周四,周五,周六,周日
1~10之间的自然数的偶数:2,4,6,8,10
对于枚举常量对应的数值,咱们也是可以自己手动进行赋初始值的:
2.枚举优点
可能有不少友友们会有这样的一个疑问:
直接使用#define 来进行常量的定义不就ok了
都这么说了,那自然是有枚举的优点了
3.枚举的使用
三· 联合(共用体)
1.联合类型的定义
联合也是自定义的一种数据类型。
注意:联合类型的成员至少有2个
2.联合的优点
联合的所有成员都是共用同一块的空间
联合的大小(sizeof)至少容下最大类型成员的大小
3.联合大小的计算
结语:
其实对于自定义类型的使用,在我们日后是很常见的。get 到自定义类型数据的使用,对后续的学习是很容易的。其实无非自定义类型就是对之前所学的内置类型进行的封装罢了。
版权归原作者 Solitary_walk 所有, 如有侵权,请联系我们删除。