目录
一、计算结构体的大小
1.1 结构体的计算并不是简单的类型加运算
1.2 内存对齐
1.2.1 内存对齐规则
1.2.2 图解内存对齐
二、计算位段的大小
2.1位段是什么
2.2 位段的内存分配
三、计算联合体的大小
3.1 什么是联合体
3.2 联合体的内存分配
END.
一、计算结构体的大小
1.1 结构体的计算并不是简单的类型加运算
大家可以先算一下这个结构体所占字节数是多少?
是不是按照类型直接相加存储呢?(char(1字节)+int(4字节)+char(1字节)=6)
这个结果是不是等于6呢?
为什么会等于12呢?
仅仅是将char b,和int i的位置互换了一下,就导致了结果的不同,这又是为什么呢?
这是因为,在创建结构体时存在内存对齐的这一规则,并不是我们所认为的简单的存储。
1.2 内存对齐
1.2.1 内存对齐规则
- 第一个成员在与结构体变量偏移量为0的地址处
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数=编译器默认的一个对齐数与该成员大小的较小值(vs环境下默认对齐数=8)
- 结构体总大小为最大对齐数的整数倍
- 如果结构体中嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。
如果只看概念,是比较难理解的,接下来举一些例子,帮助理解。
1.2.2 图解内存对齐
我们首先看一下刚才困扰我们的一个例子
为什么会是12.
通过上面的学习是否能够解释换位置后,结构体大小变为8
还有一种嵌套结构体的情况
根据上面规则的最后一条是否能解释为什么是16?
二、计算位段的大小
2.1位段是什么
位段和结构体非常相似
- 它的成员必须是int,unsigned int ,signed int和char
- 成员后边有一个冒号和一个数字
冒号后边的数字代表的是,占几个bit位(二进制位)
int a: 2;
int 本来是需要4个字节32个bit位(二进制位)
int a : 2;就代表a成员只占2个bit位,他的取值就是 00(0),01(1),10(2),11(3).
int b : 5;就代表b成员只占5个bit位
2.2 位段的内存分配
我们可以看到,结构体创建需要,16个字节
位段只需要8个字节
接下来我们就探讨一下位段的大小为什么会是8个字节(2个整型)
存储规则
- 位段成员可以是int,unsigned int或char
- 位段开辟空间,是根据成员来决定的,如果成员是int就一次开辟4个字节,成员是char一次开辟1个字节
- 位段是不跨平台的,因为其中有很多不确定因素,平台之间的规定是不一样的,本次在vs平台上
一个例子来说明
图解位段存储
内存中的16进制和我们换算的一致,所以也证实了我们的猜想在vs环境下是正确的
也确实只用了3个字节
三、计算联合体的大小
3.1 什么是联合体
联合体的关键字是union
大家可以看到下图中,创建的联合体成员的地址都是相同的
由此可以得出,他们共用的是同一块空间,所以联合体又被称为共用体。
联合体有一个特点:不能同时使用,因为他们使用的是同一块空间,给 a 赋值时会改变 i 的值,给 i 赋值会改变 a 的值。
3.2 联合体的内存分配
为什么会是4呢?
这是因为联合体要共用同一块空间,所以他要确保所有的成员在存放数据时都能存的下(开辟的空间足够大)
因此,联合体在开辟内存时会以最大内存变量的大小作为标准来开辟空间。
int 占用4个字节,char 占用1个字节,所以联合体要以4字节开辟空间大小
还有另一种情况
如果按照上面的方法来计算,7个字节也就够了,但最终结果是8个字节
这是因为,内存对齐和结构体相同,联合体也进行了内存对齐。
最终大小是最大对齐数的整数倍,离7最近的4的整数倍为8
如果对内存对齐数有疑问,可以返回到计算结构体的模块。
END.
Time is the soil of all the achievements in the world. Time gives the utopian pain and happiness to the creator.
时间是世界上的一切成就的土壤。时间给空想者痛苦,给创造者幸福。