美文网首页
OC底层探究(2)--内存对齐

OC底层探究(2)--内存对齐

作者: 墨守青城 | 来源:发表于2019-12-22 17:52 被阅读0次

    一、何为内存对齐

    内存对齐”应该是编译器的“管辖范围”。编译器为程序中的每个“数据单元”安排在适当的位置上。但是C语言的一个特点就是太灵活,太强大,它允许你干预“内存对齐”。如果你想了解更加底层的秘密,“内存对齐”对你就不应该再模糊了。

    二、如何内存对齐

    每个特定平台上都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过[预编译]命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。ios中默认系数为8。

    对齐规则:

    1. 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照min(对齐系数,自身长度)进行。
    2. 结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照min(对齐系数,最大数据成员长度)进行。
      下面举个🌰:
    struct Struct1 {
        char a;     // 1
        double b;   // 8
        int c;      // 4
        short d;    // 2
    } MyStruct1;
    
    struct Struct2 {
        double b;   // 8
        int c;      // 4 
        char a;     /
        short d;    // 2
    } MyStruct2;
    
    NSLog(@"%lu-%lu",sizeof(MyStruct1),sizeof(MyStruct2));
    

    上面的输出结果为:

    24-16
    

    那么是为什么两个结构体的大小输出不一致呢,我们可以按照上面的两条原则进行分析。
    先分析Struct1:

    • 根据原则1, a为第一个数据成员房子offset为0位置,占据一个字节大小。
    • b为第二个数据成员,它按照min(8,8)=8对齐,即a后面需要补足7位,使b的起始位置为8,b占据的位置为8-15。
    • 以此类推,c按照min(8,4)=4对齐,c的起始位置为16,占据16-19的位置。
    • d按照min(8,2)=2对齐,占据20-21的位置。
    • 此时Struct1的大小为22。又根据原则2,结构自身也要根据min(8,8)=8对齐,所以需要在后边补足两位,构成8的倍数,即24。

    分析完Struct1,即可同理分析出Struct2的大小了。

    • b从0开始,占据8位,位置为0-7。
    • c从8开始,占据4位,位置为8-11。
    • a的起始位置为12,占据一个字节大小。占据12位置
    • d按照min(8,2)=4对齐,a后面需要补一位,d从14开始,占据位置为14-15。
    • 此时Struct2大小为16,刚好满足原则2。

    三、为何要内存对齐

    1. 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
    2. 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。具体原因请往继续下看。
      在普通程序员心目中的内存印象,由一个个的字节组成,而CPU并不是这么看的。CPU把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的。块大小成为memory access granularity(内存读取粒度) 。
      举个🌰假设CPU要读取一个int型4字节大小的数据到寄存器中,分两种情况讨论:
      a. 数据从0字节开始
      当该数据是从0字节开始时,很CPU只需读取内存一次即可把这4字节的数据完全读取到寄存器中。
      b.数据从1字节开始
      当该数据是从1字节开始时,问题变的有些复杂,此时该int型数据不是位于内存读取边界上,这就是一类内存未对齐的数据。此时CPU先访问一次内存,读取0—3字节的数据进寄存器,并再次读取4—5字节的数据进寄存器,接着把0字节和6,7,8字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器。对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。当然,实际情况可能更复杂。

    相关文章

      网友评论

          本文标题:OC底层探究(2)--内存对齐

          本文链接:https://www.haomeiwen.com/subject/jueonctx.html