注:本文旨在記錄筆者的學習過程,僅代表筆者個人的理解,如果有表述不準確的地方,歡迎各位指正!因為涉及到的概念來源自網(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)存大小

內(nèi)存對齊的原則
- 數(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ù)倍地址開始存 儲。
- 結(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ù)倍開始存儲。)
- 收尾?作:結(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