今天我们来看看结构体和联合体的存储,新的一天,卯足精神,冲冲冲!!!
目录
结构体的存储
我们已经了解了整型类型,浮点数,字符数的存储,我们来了解一下结构体的存储,要知道结构体的存储和它们的存储方式截然不同,而结构体是什么呢?简单来说是一个能一下定义多个数据类型的结构,简单来说,当我们想一下定义多个变量时,结构体就当仁不让了,比如我们要记录一个学生的基本信息(学号,姓名,性别,成绩等等),我们就能使用它,我们一起来看看:
而另一个问题出来了,我们知道整型类型为4个字节,这里的字符数组占10个字节,这里的整型数组为12个字节,那就有很多同学就认定有16个字节(4+10+12),那它这个结构体是不是就时有16个字节呢?我们看看:
很显然,并不是16个字节,而是28个字节,那它到底是怎么存储的呢?首先我们要引入偏移量,对齐数,默认对齐数的概念。
偏移量,对齐数,默认对齐数
我们先来来了解对齐数,默认对齐数的概念。默认对齐数根据编译器不同,默认对齐数也就不同(根据编译器不同而不同),(Linux中gcc没有默认对齐数,对齐数就是成员本身大小)以vs2022为例,默认对齐数是8个字节,从上到下它们各自的字节大小分别为4,1,4,而它们各自字节大小和默认对齐数相比,哪个小,就取哪个作为它们各自的对齐数大小,得到了它们各自的对齐数大小后,就开始存放,从偏移量为0时开始存放,如果偏移量不是它们各自对齐数的倍数,那么偏移量向后移,直到为各自对齐数的倍数,然后再开始存放,将所有成员全部存放好之后,如果此时的结构体大小不是各自成员当中最大对齐数的倍数,那么此时结构体大小扩大,直到结构体大小时当中最大对齐数的倍数,此时结构体大小就确定下来了。这么说的话,是不是难以理解?我们上图:
这样看是不是茅塞顿开了?那如果结构体嵌套呢?那有该如何计算结构体大小呢呢?
怎么样?你算对了吗?我们一起来分析一下(记得参考上图):
现在,是不是对结构体有了独到的见解?并且是不是又有了新的问题?将一个结构体存好,有时候它十分浪费内存,中间空着的内存它没东西存进去,是不是十分浪费?那么有什么办法才能节省一下内存?
方法一:将相同类型的成员都放在一起
我们来体会一下:
是不是节省了不少?我们接下来看看第二种方法。
方法二:使用位段
什么是位段呢?怎么使用呢?位段其实就是限制每个成员存放的比特位,在成员变量名之后加个冒号再输你想保存的多少个比特位。我们要知道位段其实是专门来节省内存的。
那么这样的结构体是怎么来存的呢?(以上面那个结构体为例)先开辟一个字节的内存(8个比特位),然后开始存放a的数据(只存3个比特位),然后剩下的比特位继续存下一个成员数据。那么这样存放的话,就会出现两个问题,一是开辟了一个字节之后,是从左到右开始存放还是从右到左开始存放呢?很遗憾c语言标准并没有规定,所以怎么存放是根据编译器来定的。二是当继续存放下一个数据时,如果不够,剩下的比特位是浪费呢?还是继续使用呢?而我们现在以vs2022为例,开辟空间后从右向左使用,不够的比特位直接浪费掉。而当我们存储数据的时候,如果提供的比特位不够存的话,就会发生截断。我们上图理解看看:
我们上图验证一下:
那么最终这个结构体也是只占了2个字节。虽然位段能节省不少内存,但也存在很多问题。
位段的跨平台问题
首先就是int类型被当成有符号类型还是无符号类型,这个不确定(根据编译器)。其次是从左向右还是从右向左开始存储,c语言标准没有定义。再次是当存下一个成员时,不够存的话,剩下的空间是浪费还是继续使用,这个未知。最后就是位段中最大位的数目不能确定(早期是有16位机器的,16位机器上int类型是2个字节,32和64位机器上int类型是4个字节),有可能会出问题,比如我要这个数据的20个比特位,但此时在16位机器上int类型只有16个比特位,那么我这个数据从哪里开始存呢?而且也不够存啊。
位段使用的注意事项
使用了位段之后,尽量少用甚至不用&符号,因为每个字节是有地址的,但有些成员数据是在比特位里面的,而比特位是没有地址的。
联合体的存储
联合体和结构不同,结构体是每个成员都有一个"房子",而联合体不同,它是里面的每个成员都共用一个"房子",我们来刨析一下:
我们不难发现三者的地址都是一样的,也就是说里面成员的存储共用了。因此联合体也叫共用体。我们上图理解理解:
这样看,就有很多人觉得联合体的大小就是它当中最大存储字节的那个成员大小。其实不然,我们来看看这样一个联合体:
大多数人以为是5,而结果却是8。我们来说仔细分析一下:一般来说联合体的大小最小也要是它成员当中占最大字节的大小。而联合体大小也要和结构体大小一样,最终要满足其成员最大对齐数的倍数。以上图这个联合体为例,最终联合体的大小要是4(最大对齐数)的倍数,最终为8。
总结
我们只要了解它其中的知识点和逻辑,将其理清并梳理好,我们才能将其为自己所用。理解了结构体和联合体,我们又强大了一点点。向前冲!!!
标签:存储,字节,比特,联合体,位段,对齐,结构 From: https://blog.csdn.net/Qiwaw/article/details/136964519