雖然內(nèi)存是以自己為單位的,但大部分計(jì)算機(jī)CPU在處理內(nèi)存時(shí),并不會(huì)直接以字節(jié)為單位。處理為了提高讀取速度和減少出錯(cuò)幾率,通常會(huì)以2字節(jié)、4字節(jié)、8字節(jié)、16字節(jié)甚至32字節(jié)為單位來存取內(nèi)存,我們將上述這些存取單位稱為內(nèi)存存取粒度。關(guān)于更詳細(xì)的內(nèi)存對齊原理,這里不做詳細(xì)贅述,可以參考這篇文章內(nèi)存對齊。
有效對齊值
結(jié)構(gòu)體中最大字節(jié)數(shù)成員的長度和對齊模數(shù)中較小的那個(gè)值。具體參照如下表達(dá)式
有效對齊值 = min{ 結(jié)構(gòu)體重最大成員長度, 對齊模數(shù) }
對齊模數(shù):每個(gè)特定平臺(tái)編譯器都有自己默認(rèn)的對齊系數(shù)(也稱對齊模數(shù)),比如GCC中可默認(rèn)對齊模數(shù)是4(#pragma pack(4)),用戶也可以通過預(yù)編譯指令#pragma pack(x)來指定對齊模數(shù),x可以是1、2、4、8、16等來指定這一對齊模數(shù)
內(nèi)存對齊規(guī)則
內(nèi)部對齊(偏移量對齊):結(jié)構(gòu)體第一個(gè)成員的偏移量(offset)為0,以后每個(gè)成員相對于結(jié)構(gòu)體首地址的 offset 都是該成員大小與有效對齊值中較小那個(gè)值的整數(shù)倍,如有需要編譯器會(huì)在成員之間加上填充字節(jié)
偏移量 offset = min { 當(dāng)前成員長度, 有效對齊值 } 的整數(shù)倍
結(jié)構(gòu)體第一個(gè)成員的偏移量offset為0,以后的每一個(gè)成員相對于結(jié)構(gòu)體首地址的offset都是該成員大小與有效對齊值中較小的那個(gè)
外部對齊(結(jié)構(gòu)體整體對齊):結(jié)構(gòu)體的總大小為 有效對齊值 的整數(shù)倍,如有需要編譯器會(huì)在最末一個(gè)成員之后加上填充字節(jié)
結(jié)構(gòu)體的總大小 = 有效對齊值 的整數(shù)倍
實(shí)際案例
以下下案例結(jié)果統(tǒng)一測試方式
int main(int argc, const char * argv[]) {
NSLog(@"%lu", sizeof(s));
return 0;
}
案例具體分析
// 默認(rèn)對齊模數(shù):4
struct {
//4 offset = 0,占4位 [count = 4]
int x;
//1 偏移1的倍數(shù),前4個(gè)字節(jié)(0-1-2-3)被占用,偏移1的倍數(shù)從4開始站一位 offset = 4 [count = 5]
char y;
} s;
// 4+1 + (3) = 8
// 默認(rèn)對齊模數(shù):4
struct {
// 4 offset = 0,占4位 [count = 4]
int i;
// 1 偏移1的倍數(shù),前4個(gè)字節(jié)(0-1-2-3)被占用,偏移1的倍數(shù)從4開始站一位 offset = 4 [count = 5]
char c1;
// 1 偏移1的倍數(shù),前5個(gè)字節(jié)(0-1-2-3)+(4)被占用,偏移1的倍數(shù)從4開始站一位 offset = 5 [count = 6]
char c2;
} s;
// 4+1+1 + (2) = 8
// 默認(rèn)對齊模數(shù):4
struct {
//1 offset = 0,占1位 [count = 1]
char c1;
//4 偏移4的倍數(shù),前1個(gè)字節(jié)(0)被占用,偏移4的倍數(shù)前邊填充(1-2-3),從4開始站一位 offset = 4 [count = 8]
int i;
//1 偏移1的倍數(shù),前8個(gè)字節(jié)(0-1-2-3)+(4-5-6-7)被占用,偏移1的倍數(shù) offset = 8 [count = 9]
char c2;
} s;
// 1+(3)+4+1 + (3) = 12
// 有效對齊值:4
struct {
char c1; // 1 offset = 0,占1位 [count = 1]
char c2; // 1 offset = 1,占1位 [count = 2]
int i; // 4 offset = 4,占1位 [count = 8]
} s;
// 1+ 1 + (2) + 4 = 8
參考文獻(xiàn)