iOS 內(nèi)存對齊原則分析

在分析內(nèi)存對齊原則之前,我們先來分析一下在OC和C中,各種基本數(shù)據(jù)類型在32位或64位的操作系統(tǒng)中,他們所占的字節(jié)數(shù)是否相同呢?各占多少字節(jié)數(shù)呢?

image.png

根據(jù)上圖的數(shù)據(jù)類型所占的字節(jié)數(shù),我們就有了內(nèi)存對齊的原則:

    1. 數(shù)據(jù)成員對齊規(guī)則:結(jié)構(gòu)(struct)(或聯(lián)合union)的數(shù)據(jù)成員,第一個(gè)數(shù)據(jù)成員放在offset為0的地方,以后每個(gè)數(shù)據(jù)成員存儲的起始位置要從該成員大小或者成員的子成員大?。ㄖ灰摮蓡T有子成員,比如說是數(shù)組,結(jié)構(gòu)體等)的整數(shù)倍開始(比如int4字節(jié),則要從4的整數(shù)倍地址開始存儲)。
    1. 結(jié)構(gòu)體作為成員:如果一個(gè)結(jié)構(gòu)體里面有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開始存儲。(struct a里存有 struct b, b里有char,int,double,等元素,那b應(yīng)該從8的整數(shù)倍開始存儲)。
    1. 收尾工作:結(jié)構(gòu)體的總大小,也就是 sizeof的結(jié)果,必須是其內(nèi)部最大成員的整數(shù)倍,不足的要補(bǔ)齊。
我們用一個(gè)案例來分析字節(jié)對齊原則:
struct One {
    double a;   // 8   0...7
    int b;      // 4   8 9 10 11
    char c;     // 1   12
    short d;    // 2   14 15
} CSOne;
// 內(nèi)部需要的大小為: 16
// 最大屬性: 8
// 結(jié)構(gòu)體整數(shù)倍:16

struct Two {
    double a;  // 8 0...7
    char b;    // 1 8
    int c;     // 4 12 13 14 15
    short d;   // 2 16 17
} CSTwo;
// 內(nèi)部需要的大小為: 18
// 最大屬性: 8
// 結(jié)構(gòu)體整數(shù)倍:24

struct Three {
    double a;  // 8 0...7
    char b;    // 1 8
    short c;   // 2 10 11
    int d;     // 4 12 13 14 15
} CSThree;
// 內(nèi)部需要的大小為: 16
// 最大屬性: 8
// 結(jié)構(gòu)體整數(shù)倍:16

以上3個(gè)結(jié)構(gòu)體中,有a , b, c, d 4 個(gè)完全一樣的屬性,只是它們的位置不同,那么這3個(gè)結(jié)構(gòu)體所占的字節(jié)數(shù)是否相同呢?

   NSLog(@"%lu ---- %lu ---- %lu", sizeof(CSOne), sizeof(CSTwo), sizeof(CSThree));
// 控制臺打印的數(shù)據(jù):
   16 ---- 24 ---- 16

分析:通過控制臺打印的數(shù)據(jù),我們得出是不相同的,為什么會這樣呢?他們只是換了一下位置就不同?這是由于結(jié)構(gòu)體內(nèi)屬性的字節(jié)數(shù)不同,屬性存儲時(shí)內(nèi)存對齊原則導(dǎo)致的。

  • 我們先分析結(jié)構(gòu)體 Two
image.png

分析:adouble類型,占用8字節(jié),由于是第一個(gè)數(shù)據(jù)成員,則放在 offset0的地方( 0...7 ), bchar 類型占用 1 字節(jié),根據(jù)結(jié)構(gòu)體內(nèi)存對齊原則,由于 81的倍數(shù),則b 存在8的位置,再繼續(xù)存儲c,由于cint類型占 4字節(jié),而9, 10, 11位置都不是 4 的倍數(shù),所以不能存儲,到12的位置,124的倍數(shù),則開始存儲c (12, 13, 14, 15), 再開始存儲 d,由于 dshort 類型占用 2 字節(jié),從 16 的位置開始存儲,162的整數(shù)倍可以存儲,則d存儲在(16, 17)的位置。存儲完a , b, c, d,后 ,內(nèi)部需要的大小為18字節(jié),根據(jù)內(nèi)存對齊第三條,則需要 24字節(jié)存儲空間。

接下來我們分析一下結(jié)構(gòu)體嵌套類型的數(shù)據(jù)對齊方式:

struct Four {
    double a;
    char b;
    int d;
    short c;
    struct Three *e;
} CSFour;

通過控制臺打印的數(shù)據(jù):

   NSLog(@"%lu", sizeof(CSFour));
// 打印信息:
   32

通過代碼分析,我們可以得出,由于結(jié)構(gòu)體指針只占8 字節(jié),所以 結(jié)構(gòu)體 CSFour 中的結(jié)構(gòu)體 e 只占8字節(jié),其他的屬性經(jīng)過之前的分析得出大小為 18 字節(jié), 再加上結(jié)構(gòu)體 e的大小為 8字節(jié),根據(jù)內(nèi)存對齊原則,可得出 結(jié)構(gòu)體 CSFour 的大小為32 字節(jié)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容