重学OC第二篇:内存对齐

本文详细探讨了内存对齐的原因,包括平台兼容性和性能优化。阐述了结构体内存对齐的原则,包括#pragma pack宏的影响,以及在没有该宏时的对齐规则。还介绍了操作系统层面的内存对齐,如Mac系统的16字节对齐,并分析了malloc、calloc、realloc的内存分配差异。最后,文章提到了OC类属性的存储优化,展示了实例属性的内存布局。
摘要由CSDN通过智能技术生成

内存对齐

1. 为什么要进行内存对齐

  • 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  • 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。 CPU 并不是以字节为单位存取数据的,cpu把内存当成是一块一块的,块的大小可以是2,4,8,16 个字节,因此CPU在读取内存的时候是一块一块进行读取的,块的大小称为(memory granularity)内存读取粒度。
    我们再来看看为什么内存不对齐会影响读取速度?
    假设CPU要读取一个4字节大小的数据到寄存器中(假设内存读取粒度是4),分两种情况讨论:
    第一种情况:数据从0字节开始。当数据从0字节开始的时候,直接将0-3四个字节完全读取到寄存器,结算完成了。
    第二种情况:数据从1字节开始。当数据从1字节开始的时候,问题很复杂,首先先将前4个字节读到寄存器,并再次读取4-7字节的数据进寄存器,接着把0字节,4,6,7字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器,对一个内存未对齐的寄存器进行了这么多额外操作,大大降低了CPU的性能。

2. 结构体内存对齐原则

2.1在有#pragma pack宏的情况下

结构体的自身宽度就是宏上规定的数值大小,所有内存都按照这个宽度去布局
#pragma pack 参数只能是 ‘1’, ‘2’, ‘4’, ‘8’, ‘16’

2.2在没有#pragma pack宏的情况下

结构体的自身宽度有最大成员属性的宽度决定。

1、第一个成员的首地址为0.

2、每个成员的首地址是自身大小的整数倍; 如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。

3、结构体的总大小,为其成员中所含最大元素类型的整数倍。

struct Outside {
    //(7):根据第3条,最大元素类型为long double 16字节,a + b +c = 7不是16的整数位,补齐为16,可知Outside大小16+32=48字节
    char a;   //(1):第一个成员,首地址为0字节位,char占1个字节
    int b;		//(2):int为4个字节,根据第2条原则,首地址为4
    short c;	//(3):short为2个字节,首地址为8
    struct Inside {
     //(6):根据第2条,首地址为16,根据第3条,可知Inside大小为32字节
        int a;  //(4):int为4个字节,首地址为inside结构体的0字节位
        long double b; //(5):long double为16字节,根据第2条原则,首地址为inside结构体的第16字节位
    } inside;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值