结构体:
结构体就是一个可以存放多个类型的集合,如图
结构体的对齐规则
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值
结构体为什么要内存对齐?
1.平台原因
不是所有平台都可以在任意位置访问数据,有些平台只能在特定位置(比如规定int类型只能是在4的整数倍处访问,double类型只能在8的整数倍处访问)访问数据,否则会抛出硬件异常
2.性能原因
假设一个机器每次访问数据为4个字节,则访问的地址必须是4的倍数,如果没有内存对齐那么
我们对i数据进行访问时则需要访问两次才可以得到i的数据,如果内存对齐了,我们只需要访问一次就可以访问到i的数据;内存对齐实际上就是一种以空间换时间的方式。
注:我们写代码的过程中可以调整类型的顺序来减少空间
大小为12
大小为8
联合体:
联合体各元素采用内存共享的方式存储,当其中一个数据改变会影响其他数据。
以小端存储为例,当向i变量输入10000,此时内存上的是10 27 00 00
再向c里输入1时,内存则变为01 27 00 00
联合体的大小的计算
1.先求出该结构体最大元素的大小,保证最大元素可以存储
2.从最大元素的大小和编译器内存对齐的规定的大小中取较小值,使得结构体大小大于最大元素的大小,且为较小值的整数倍
注意:联和体内数组的对齐数是数组所存储类型的对齐数
那联合体有什么应用场景呢?
如图当我们要设计一个抽奖的礼物列表,抽奖只会抽中其中一样就可以如上图设计来减少内存占用;这样设计类似于多态
枚举
枚举就是在这个结构里给一个整形常量取一个别名,也是就是之前的宏定义那样,当时书写起来比宏定义简单,放在一个结构体里更好维护
而且将变量定义在枚举类型里面会有类型检查,如果直接给枚举变量赋值时只能给enum内的常量名,不能给数字,否则会编译报错,但是在使用scanf给枚举常量赋值时是输入对应数字的,要注意。(要测试的话要在c++下,c语言的检查并不严格)
如果没给初始值的话第一个默认为0,后面的没给值的话就是前一个+1;所以RED,GREEN,BLUE分别对应0,1,2
RED,GREEN,BLUE分别对应1,2,3
我们也可以自由赋值
位段
位段是基于结构体的一中特殊数据结构,位段只能是int或者是char类型,位段的目的是减少内存,但使用了位段也会降低效率,所以当我们内存的需求非常大时才会使用,(比如在网络中,如下图)
位端的大小计算
1.如果相邻的数据类型相同且相加的比特位数没有超过最大值就会合并到一起
2.如果相邻的数据结构不同就按照结构体的方式计算
3.位段也是要对齐到对齐数的整数倍
位段不具有跨平台性,理由如下
