C++ 内存对齐
注:本文代碼測試環(huán)境為win7 X64 cpu, 編譯器為gcc4.7.1 和 vs2010
?
內(nèi)存對齊是編譯器為了便于CPU快速訪問而采用的一項技術(shù)
我們先從一個例子開始,對下面的類(或者結(jié)構(gòu)體)
class node
{
char c;
int i;
short s;
}no;
sizeof(no)的值是多少呢,如果你的回答是7(1+4+2),那么你應(yīng)該認真閱讀下面的內(nèi)容。可以在編譯器上試試,輸出的結(jié)果是12,這就是內(nèi)存對齊的結(jié)果。
?
為什么要進行內(nèi)存對齊呢?
編譯器一般按照幾個字節(jié)對齊呢?本文中兩個編譯器默認按照類中最大類型長度來對齊,我么也可以使用語句#pragma pack(i)(i = 1,2,4,8,16)來設(shè)置對齊字節(jié)數(shù)目,vs還可以在項目屬性-配置屬性-c/c++-代碼生成-結(jié)構(gòu)成員對齊設(shè)置。
?
對齊規(guī)則如下:
我們通過以下幾個實例來分析
實例1:(沒有指定對齊字節(jié),則n = 最大成員(int i)的大小4)
class node
{
char c;?? //放在位置0,位置區(qū)間[0]
int i;????? //4 = n, 那么放置起始位置應(yīng)該是4的倍數(shù),即4,位置區(qū)間為[4~7]
short s; //2 < n,那么放置起始位置應(yīng)該是2的倍數(shù),即8,位置區(qū)間為[8~9]
}
此時成員共占用[0~9]10個字節(jié),還要整體對齊,大小應(yīng)該是4的倍數(shù),即12
?
實例2:(假設(shè)指定對齊字節(jié)為8,那么n = min(8,4) = 4)
class node
{
int i; //放在位置0,位置區(qū)間[0~3]
char c; //1 < n, 那么放置起始位置應(yīng)該是1的倍數(shù),即4,位置區(qū)間為[4]
short s; //2 < n,那么放置起始位置應(yīng)該是2的倍數(shù),即6,位置區(qū)間為[6~7]
}
成員共占據(jù)[0~7]8個字節(jié),剛好是4的倍數(shù),因此大小是8
?
實例3:(假設(shè)指定對齊字節(jié)是2,則n = min(2,4) = 2)
class node
{
char c; //放在位置0,位置區(qū)間[0]
int i; //4 > n, 那么放置起始位置應(yīng)該是2的倍數(shù),即2,位置區(qū)間為[2~5]
short s; //2 = n,那么放置起始位置應(yīng)該是2的倍數(shù),即6,位置區(qū)間為[6~7]
}
此時成員共占用[0~7]8個字節(jié),剛好是4的倍數(shù),因此大小是8
?
實例4:(按照默認設(shè)置)
class temp?
{?
??? char c;?
??? int i;?
??? short s1;?
};
由實例1可知,默認對齊情況下,temp的大小是12,temp的對齊字節(jié)數(shù)是:三個成員取最大的,即為4;
對于node,n = 其三個成員對齊字節(jié)數(shù)取最大,即等于t的對齊字節(jié)數(shù),也就是 4。
class node
{
char c; //放在位置0,位置區(qū)間[0]
temp t; //4(temp的對齊字節(jié)數(shù)) = n, 那么放置起始位置應(yīng)該是4的倍數(shù),即4,位置區(qū)間為[4~15]
short s; //2 < n,那么放置起始位置應(yīng)該是2的倍數(shù),即16,位置區(qū)間為[16~17]
}
此時成員共占用[0~17]18個字節(jié),還要整體對齊,大小應(yīng)該是4的倍數(shù),因此大小是20
?
實例5:(默然設(shè)置)
對于node,n = 其三個成員對齊字節(jié)數(shù)取最大,即等于d的對齊字節(jié)數(shù),也就是 8。
class node
{
temp t; //放在位置0,位置區(qū)間[0~11]
double d; //8(temp的對齊字節(jié)數(shù)) = n, 那么放置起始位置應(yīng)該是8的倍數(shù),即16,位置區(qū)間為[16~23]
short s; //2 < n,那么放置起始位置應(yīng)該是2的倍數(shù),即24,位置區(qū)間為[24~25]
}
此時成員共占用[0~25]26個字節(jié),還要整體對齊,大小應(yīng)該是8的倍數(shù),因此大小是32.
?
類繼承時的內(nèi)存對齊
考慮如下類
class A
{
int i;
char c1;
}
class B:public A
{
char c2;
}
class C:public B
{
char c3;
}
sizeof(C)結(jié)果是多少呢,gcc和vs給出了不同的結(jié)果,分別是8、16
gcc中:C相當于把所有成員i、c1、c2、c3當作是在一個class內(nèi)部,(先繼承后對齊)
vs中:對于A,對齊后其大小是8;對于B,c2加上對齊后的A的大小是9,對齊后就是12;對于C,c3加上對齊后的B大小是13,再對齊就是16 (先對齊后繼承)
關(guān)于c++對象繼承后的內(nèi)存布局,更詳細的分析可以《深度探索參考c++對象模型》第三章
?
參考資料:
zhyjunfov的ChinaUnix博客:gcc的內(nèi)存對齊
【版權(quán)聲明】轉(zhuǎn)載請注明出處:http://www.cnblogs.com/TenosDoIt/p/3590491.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
- 上一篇: 配置Ubuntu Server高速apt
- 下一篇: C++ set的一些用法