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

還真是!!!!!
複製代碼

你們能夠經過多寫點例子來驗證。。看來內存對齊的規則仍是挺好用的。。

相關文章
相關標籤/搜索