iOS底層探索:結(jié)構(gòu)體內(nèi)存對齊

注:本文旨在記錄筆者的學習過程,僅代表筆者個人的理解,如果有表述不準確的地方,歡迎各位指正!因為涉及到的概念來源自網(wǎng)絡(luò),所以如有侵權(quán),也望告知!

前言

本文主要是深入了解一下iOS底層對結(jié)構(gòu)體內(nèi)部字節(jié)進行的對齊原理。

正文

首先我們定義了三個結(jié)構(gòu)體 LGStruct1、 LGStruct2和 LGStruct3 ,然后通過控制臺打印出三個結(jié)構(gòu)體類型的內(nèi)存大小。

struct LGStruct1 {
    double a;  
    char b;     
    int c;      
    short d;    
}struct1;

struct LGStruct2 {
    double a;   
    int b;      
    char c;     
    short d;    
}struct2;

struct LGStruct3 {
    double a; 
    int b;     
    char c;     
    short d;    
    struct LGStruct1 e;
}struct3;

NSLog(@"%lu-%lu-%lu",sizeof(struct1),sizeof(struct2),sizeof(struct3));

可以看到,控制臺的打印結(jié)果如下:

那么你是不是跟筆者存在同樣的疑惑,LGStruct1、LGStruct2兩個結(jié)構(gòu)體擁有的變量數(shù)量跟類型都大同小異,到底是什么原因?qū)е聝蓚€結(jié)構(gòu)體在內(nèi)存大小的表現(xiàn)上會有截然不同的結(jié)果?LGStruct3的內(nèi)存大小又是如何計算出來的?

基本數(shù)據(jù)類型內(nèi)存大小

image

內(nèi)存對齊的原則

  1. 數(shù)據(jù)成員對?規(guī)則:結(jié)構(gòu)(struct)(或聯(lián)合(union))的數(shù)據(jù)成員,第 ?個數(shù)據(jù)成員放在offset為0的地?,以后每個數(shù)據(jù)成員存儲的起始位置要 從該成員??或者成員的?成員??(只要該成員有?成員,?如說是數(shù)組, 結(jié)構(gòu)體等)的整數(shù)倍開始(?如int為4字節(jié),則要從4的整數(shù)倍地址開始存 儲。
  2. 結(jié)構(gòu)體作為成員:如果?個結(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ù)倍開始存儲。)
  3. 收尾?作:結(jié)構(gòu)體的總??,也就是sizeof的結(jié)果,必須是其內(nèi)部最? 成員的整數(shù)倍,不?的要補?。

案例解析

了解系統(tǒng)對結(jié)構(gòu)體 內(nèi)存對齊的原則后,我們回過頭再看一下文章一開頭的 三個結(jié)構(gòu)體LGStruct1、LGStruct2和LGStruct3 。

結(jié)構(gòu)體 LGStruct1,通過 內(nèi)存對齊規(guī)則計算 過程如下:

  • 變量a: **double ** 占8個字節(jié),從0位置開始,則 0-7 存儲 a

  • 變量b: **char ** 占1個字節(jié),從8位置開始,此時8是1的整數(shù)倍,則 8 存儲 b

  • 變量c: int 占4個字節(jié),從9位置開始,但是此時9不是4的整數(shù)倍,因此需要往后繼續(xù)尋找,找到最接近的能整除4的12位置,則 12-15 存儲 c

  • 變量d: **short ** 占2個字節(jié),從16位置開始,此時16是2的整數(shù)倍,則16-17 存儲 d

  • 收尾:LGStruct1需要的內(nèi)存大小為18字節(jié),而LGStruct1中最?成員變量字節(jié)數(shù)是8字節(jié),內(nèi)存大小18字節(jié)不是內(nèi)部最?成員的整數(shù)倍,所以必須向上補齊,補齊后的最終大小為24字節(jié)

結(jié)構(gòu)體LGStruct2,通過內(nèi)存對齊規(guī)則計算過程如下:

  • 變量a: double 占8個字節(jié),從0位置開始,則 0-7 存儲 a

  • 變量b: int 占4個字節(jié),從8位置開始,此時8是4的整數(shù)倍,則 8-11 存儲 b

  • 變量c: char 占1個字節(jié),從12位置開始,此時12是1的整數(shù)倍,則 12 存儲 c

  • 變量d: short 占2個字節(jié),從13位置開始,但是此時13不是2的整數(shù)倍,因此需要往后繼續(xù)尋找,找到最接近的能整除2的14位置,則 14-15 存儲 d

  • 收尾:LGStruct2需要的內(nèi)存大小為16字節(jié),LGStruct2中最?成員變量字節(jié)數(shù)是8字節(jié),內(nèi)存大小16字節(jié)剛好是內(nèi)部最?成員的整數(shù)倍,所以最終大小為16字節(jié)

結(jié)構(gòu)體LGStruct3,通過內(nèi)存對齊規(guī)則計算過程如下:

  • 變量a: double 占8個字節(jié),從0位置開始,則 0-7 存儲 a

  • 變量b: int 占4個字節(jié),從8位置開始,此時8是4的整數(shù)倍,則 8-11 存儲 b

  • 變量c: char 占1個字節(jié),從12位置開始,此時12是1的整數(shù)倍,則 12 存儲 c

  • 變量d: short 占2個字節(jié),從13位置開始,但是此時13不是2的整數(shù)倍,因此需要往后繼續(xù)尋找,找到最接近的能整除2的14位置,則 14-15 存儲 d

  • 變量e:內(nèi)嵌的LGStruct1結(jié)構(gòu)體,LGStruct1內(nèi)部最?元素的大小是8字節(jié),需要從8的整數(shù)倍位置開始存儲,存儲方式同上LGStruct1結(jié)構(gòu)體,則 16-33 存儲 e

  • 收尾:LGStruct3需要的內(nèi)存大小為34字節(jié),LGStruct3中最?成員變量字節(jié)數(shù)是8字節(jié),內(nèi)存大小34字節(jié)不是內(nèi)部最?成員的整數(shù)倍,所以必須向上補齊,補齊后的最終大小為40字節(jié)

推薦??:

如果你想一起進階,不妨添加一下交流群642363427

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

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

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