iOS底层探索--内存对齐

对于大多数研究底层的程序员,对内存对其应该都不陌生,今天小生来献丑一波。程序员

内存对齐的定义

内存对齐 应该是编译器的“管辖范围”。编译器为程序中的每一个“数据单元”安排在适当的位置上。
对于大部分研究过底层的程序员来讲,“内存对齐”对他们来讲都应该是“透明的”。
复制代码

为何要内存对齐

因为本人文采很差,借用下百度百科的解释。数组

  • 一、平台缘由(移植缘由):不是全部的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,不然抛出硬件异常。
  • 二、性能缘由:数据结构(尤为是栈)应该尽量地在天然边界上对齐。缘由在于,为了访问未对齐的内存,处理器须要做两次内存访问;而对齐的内存访问仅须要一次访问。

内存对齐的规则

(很长,说实话,我也懒得看下去。。不要紧,后面我会举例解释)markdown

  • 1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第

一个数据成员放在offset为0的地方,之后每一个数据成员存储的起始位置要 从该成员大小或者成员的子成员大小(只要该成员有子成员,好比说是数组, 结构体等)的整数倍开始(好比int为4字节,则要从4的整数倍地址开始存 储。 min(当前开始的位置mn) m=9 n=4 那么 9 10 11 12 、 就要从12开始存储数据结构

  • 2:结构体做为成员:若是一个结构里有某些结构体成员,则结构体成员要从

其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b 里有char,int ,double等元素,那b应该从8的整数倍开始存储.)oop

  • 3:收尾工做:结构体的总大小,也就是sizeof的结果,.必须是其内部最大

成员的整数倍.不足的要补⻬性能

各种型所占字节

我也知道你们这个表都知道,可是不把图啪上感受没有仪式感spa

举例说明内存对齐

上面罗里吧嗦的终于结束了。只看理论啥收获都没有感受,仍是不让代码验证解释比较痛快。code

我会经过结构体来讲明orm

  • 例1:
注: {}表明解释说明 。
struct XGStruct1 {
    double a;   // 8{所占字节数} (0{开始位置}-7{结束位置}){所占字节位置}
    char b;     // 1{所占字节数} [8{开始位置} 1{所占字节数}] (8){存储字节位置}
    int c;      // 4{所占字节数} [9{开始位置} 4{所占字节数}] 9 10 11 (12 13 14 15){存储字节位置}
    short d;    // 2{所占字节数} [16{开始位置} 2{所占字节数}] (16 17){存储字节位置}
}struct1;

解释说明:
内存对齐规则1:开始位置必须是所占字节数的整数倍,才能开始存。
(举例:char b,因为开始位置是所占字节数的整数倍能够直接存,int c ,开始位置是从9,并非4的整数倍,因此从12开始存)

存储大小是:18{0-17}

因为结构体中存在double为最大字节数:8
(内存对齐规则3:所占内存必须是最大字节数的整数倍。因此必须是8的整数倍。18-->24)

因此所占内存大小是24.
复制代码
输出log确认下:
NSLog(@"%lu",sizeof(struct1));

log输出:24
复制代码
  • 例2:

这个应该就比较形象了。内存

struct XGStruct2 {
    int b;      //4{所占字节数} [0{开始位置} 4{所占字节数}],(0 1 2 3){存储字节位置}
    char c;     //1{所占字节数} [4{开始位置} 1{所占字节数}], (4){存储字节位置}
    short d;    //2{所占字节数} [5{开始位置} 2{所占字节数}], 5 (6 7){存储字节位置}
    short e;    //2{所占字节数} [8{开始位置} 2{所占字节数}], (8 9){存储字节位置}
}struct2;

解释说明:
一、内存所占大小是 10(0-9)
二、内存中最大的字节是int(4),因此是4的整数倍。
理论结果:12

验证:
NSLog(@"%lu",sizeof(struct2));
输出:
12
复制代码

内存对齐规则的扩展

以上2个例子应该能够说明内存对其规则了。我相信你们也都懂了。那么,我们来一波进阶:结构体嵌套结构体。

继续用上面两个例子,而后加以改正:

struct XGStruct1 {
    double a; 
    char b;  
    int c;     
    short d;    
}struct1;
//已证

struct XGStruct2 {
    int b;      
    char c;     
    short d;    
    short e;    
}struct2;
//已证

咱们把XGStruct2 改变下,加入XGStruct1,变成XGStruct3:
struct XGStruct3 {
    int b;      
    char c;     
    short d;    
    short e;
    struct XGStruct1 xgs;
}struct3;

你们能够先想一想下,所占内存大小?
复制代码

解释了啊:

首先。咱们先经过规则,大概猜一下,会是什么样子的。。

而后我要开始验证了啊。。

先换一种好说明的写法
struct XGStruct3 {
    int b;      //4{所占字节数} [0{开始位置} 4{所占字节数}],(0 1 2 3){存储字节位置}
    char c;     //1{所占字节数} [4{开始位置} 1{所占字节数}], (4){存储字节位置}
    short d;    //2{所占字节数} [5{开始位置} 2{所占字节数}], 5 (6 7){存储字节位置}
    short e;    //2{所占字节数} [8{开始位置} 2{所占字节数}], (8 9){存储字节位置}
    struct XGStruct4 {
        double a;// [10 8] 10 11 12 13 14 15 (16 17 18 19 20 21 22 23)
        int b;   // [24 4] (24 25 26 27)
        char c;  // [28 1] (28)
        short d; // [29 2] 29 (30 31)
    }xgs;
}struct3;

所占大小是32 (0-31)
里面最大类型是double(8),又是8的倍数,那岂不是结果是32,

验证一波:
NSLog(@"%lu",sizeof(struct3));
输出:
32

还真是!!!!!
复制代码

你们能够经过多写点例子来验证。。看来内存对齐的规则仍是挺好用的。。

相关文章
相关标签/搜索