C语言中的内存对齐

本文详细介绍了C语言中的内存对齐概念,包括为何要进行字节对齐,如何进行字节对齐以及对齐的规则。内存对齐的主要目的是提高数据存取速度,确保CPU按照特定单位进行高效读取。通过对结构体成员和整体大小的对齐规则进行解析,展示了如何在结构体中正确地存储不同类型的变量,以达到最佳的内存利用率和性能效果。

1、概述

我们经常用sizeof()运算符求取某个结构体占用空间的大小,实际上,亲自在编程平台上进行实践的小伙伴会发现,求取的占用空间大小并不是简单的将结构体中所有元素各自的占用空间进行相加,反而求得值会大于该加和值,这是为什么呢?这就是涉及到字节对齐的问题啦。

2、什么是字节对齐?

按照理论上讲,对于任何变量的访问都是可以从任何地址开始访问,但实际上,访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按照一定规则排列,而不是简单的顺序排列,这就是内存对齐

3、为嘛要字节对齐?

①首先要明确CPU是按照块来对内存中的数据进行读取,根据不同的平台,通常按照2、4、8、16个字节来进行数据读取。
在这里插入图片描述
如上图所示,每次CPU读取数据时,每2或4或8…来读取,而不是一个一个自己的去读
②以下面两个变量为例,char a (占用1个字节)和int b(占用4个字节);
在这里插入图片描述
假设CPU默认情况下按照4个字节读取数据,那么第一次读取,会读到a以及b的前三个字节,第二读取b的第四个字节以及后面其他的数据,这样要想完整的知道a和b 的值就需要对两次读到的数据先进行分离,再重新组合,使该过程变得比较的繁琐,大大降低数据处理速度。
因此,如果按照下面规则进行数据存储呢?将a存储在0-3字节,b存储在4-7字节,是不是每次CPU读到的就是源数据了呢,就不用费心思再去做数据分离和组合了对不对。
在这里插入图片描述
所以,字节对齐的目的就是提高数据的存取速度。

4、如何字节对齐?有什么规则?

①对于标准数据类型(内建数据类型),内存地址是该种数据类型的整数倍,如int类型,地址要是4字节的整数倍;
②对于非标准数据类型,比如结构体,由于结构体通常包含不同类型的数据,因此需要准守一定的规则
1)结构体成员对齐,第一个结构体成员的应该放在偏移地址为0 的地方,往后的每个结构体成员需要从最小长度min_L的整数倍的地方开始存放。min_L通过是该数据类型的长度和计算机默认存储模式长度取最小值确定(比如32位机器中int型占4个字节,机器默认存储是8个字节,那么存储是按照4的整数倍进行,如果机器默认存储是2个字节,那么存储是按照2的整数倍进行)
2)结构体的总大小,即sizeof() 的计算结果,是结构体内部占用最大字节的数据类型长度和机器默认存储模式字节长度的最小值的整数倍,不足需要补齐。
例如:
//假设默认存储8个字节//
typedef struct_STUDENT1{
int a ;// 从4的倍数开始,0-3
char b://从1的倍数开始,4(实际占用4-7)
double c;//从8的倍数开始,8-15
float d;//从4的倍数开始,16(16-19)
}Student1;

//结构体内部对齐后大小20个字节(0-19);整体对齐,要满足最大字节类型的整数倍,即8的整数倍,故为24,即sizeof(student)=24

3)结构体嵌套时,如果结构体M中包含结构体N,还是按照最大字节成员类型大小对齐,但是结构体N的起点为N内部最大字节成员的整数倍(如,结构体M中嵌套结构体N,N中有int char 和double ,那么N应该从8的整数倍开始)
typedef struct_STUDENT2{
char a ;// 从1的倍数开始,0(0-7)
Student b://从内部成员最大字节整倍数开始,即从8开始存储,(占用第8-31字节)
double c;//从8的倍数开始,即32-39
}Student2;

//结构体内部对齐后大小40个字节(0-19);整体对齐,要满足最大字节类型的整数倍,即8的整数倍,故为40,即sizeof(student)=40

5、参考资料

【1】https://www.bilibili.com/video/BV1PK411N7bU?from=search&seid=5419116297939382731&spm_id_from=333.337.0.0

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值