内存对齐

一个常见的例子

struct s1{
    char a;
    char b;
    int c;
}
struct s2{
    char a;
    int c;
    char b;
}

sizeof(s1) = 8;
sizeof(s2) = 12;

内存对齐

内存地址对齐,是一种在计算机内存中排列数据、访问数据的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐

对于基本数据类型,其地址是内存对齐的:基本类型数据对齐就是数据在内存中的偏移地址必须等于一个字的倍数
而结构体对齐:为了保证访问结构体数据的性能,可能需要在上一个数据结束的地方和当前数据开始的地方插入一些纯粹占位的字符。包括结构体内部元素类型的对齐和结构体本身的对齐

内存对齐的规则为:

1、 对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数,这个数据成员的自身长度) 的倍数。
2、 在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

看上面中s2的例子,假设编译默认pack(8), a偏移0,c为int,所以其偏移应该是是min(8,4)=4 ,所以需要在a,c之间插入3个填充字节,再看b,其偏移为min(8,1)=1;所以不用考虑。已有的数据占了1+3+4+1=9字节。现在考虑第二条规则,结构体本身也要对齐(这样是为了当声明结构体数组时,能够访问更快),最大的数据成员为int,4字节,min(8,4)=4,所以要加上3字节,9+3=12凑成4的倍数。所以sizeof(s2)=12;
所以上面结构体实际为

struct s2{
    char a;
    char pad[3];
    int c;
    char b;
    char pad[3];
}

那么一个例子
struct{ char a; char b;} 其 size是2bytes. 而不是一定要填充到4字节。因为根据第二条,对齐按char的数据长度来,就是char的倍数即可,所以是 2bytes.

注意数组元素之间是没有填充位的,加了反而会浪费空间,无论声明基本元素还是结构体元素的数组。如果是类型长度小于等于4字节,那么不需要加填充位,因为一次访问一个字就可以把元素取出来,如果大于4字节,那么本来就需要多次访问。
为了优化,重新排列结构体元素顺序或者故意加一些填充位也是可以的。比如OpenCV的图像像素,行首的地址通常需要字节对齐,所以行与行之间的偏移 widthStep不一定等于width*channels, 而是 widthStep = (width*channels + align-1) /align *align;

可以用 #pragma pack来改变编译器默认的内存设置

#pragma pack(push) 
#pragma pack(2)
// your struct define
#pragma pack(pop)

内存对齐的好处

  • 加快数据的访问速度。

计算机内部32位的地址总线,32位的数据总线,所以每次能读取4个字节的数据,而并非一个字节一个字节读取。最低2位A[0],A[1]是不用于寻址,A[2-31]才能存储器相连,因此只能访问4的倍数地址空间
假设一个int 4字节,如果其地址是对齐的(假设是0x3FFFFFF0),那么只需要一次访问内存就能获取4个字节,但是如果其地址是非对齐的(比如0x3FFFFFF1),那么需要连续2次访问内存,分别访问0x3FFFFFF1获得后面3个字节和0x3FFFFFF4获得前面1个字节,并合起来,然后才能获取这个int数据。而由于CPU的处理速度远高于访问内存的速度,所以显然前者要快很多

  • 便于程序移植。而在有些CPU架构上,并不支持非对齐地址的访问,所以如果代码中字节不对齐,对程序移植也会有影响

参考:
内存地址对齐
内存对齐的规则以及作用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值