c++对象长度之内存对齐(2)
文章目錄
- 內(nèi)存對(duì)齊
- 例題a
- 例題b
- 例題c
內(nèi)存對(duì)齊
在VC++6.0中,類和結(jié)構(gòu)體中的數(shù)據(jù)成員是根據(jù)它們?cè)陬惢蚪Y(jié)構(gòu)體中出現(xiàn)的順序來(lái)依次申請(qǐng)申請(qǐng)內(nèi)存空間的,由于內(nèi)存對(duì)齊的原因,它們并不一定會(huì)像數(shù)組那樣連續(xù)地排列。由于數(shù)據(jù)類型的不同,因此占用的內(nèi)存空間大小也會(huì)不同,因此占用的內(nèi)存空間大小也會(huì)不同,在申請(qǐng)內(nèi)存時(shí),會(huì)遵守一定的規(guī)則。
要找對(duì)齊的話,我個(gè)人感覺應(yīng)該先找到
編譯器的指定對(duì)齊值,因?yàn)榻Y(jié)構(gòu)體中的當(dāng)前數(shù)據(jù)成員類型長(zhǎng)度為M,指定的對(duì)齊值是N,那么實(shí)際的對(duì)齊值為q=min(M,N),其成員的地址安排在q的倍數(shù)上。
但是,并非設(shè)定了默認(rèn)對(duì)齊值就將結(jié)構(gòu)體的對(duì)齊值鎖定。如果結(jié)構(gòu)體中的數(shù)據(jù)成員類型最大值為M,指定的對(duì)齊值是N,那么實(shí)際對(duì)齊值為q=min(M,N)
三準(zhǔn)則如下:
a.數(shù)據(jù)成員對(duì)其規(guī)則:結(jié)構(gòu)(或聯(lián)合)的數(shù)據(jù)成員,第一個(gè)數(shù)據(jù)成員放在offset為0的地方,以后每個(gè)數(shù)據(jù)成員存儲(chǔ)的子成員大小(只要該成員有子成員,比如說(shuō)是數(shù)組,結(jié)構(gòu)體等)的整數(shù)倍開始(比如int 在32位機(jī)為4字節(jié)則要從4的整數(shù)倍地址開始存儲(chǔ))
b.結(jié)構(gòu)體作為成員:如果一個(gè)結(jié)構(gòu)里有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)體成員要從其內(nèi)部最大元素的整數(shù)倍地址開始存儲(chǔ).(struct a里存有 struct b,b里有 char ,int ,double 等元素,那b應(yīng)該從8的整數(shù)倍開始存儲(chǔ).)
c.收尾工作:結(jié)構(gòu)體的總大小,也就是sizeof的結(jié)果,必須是其內(nèi)部最大成員的整數(shù)倍,不足的要補(bǔ)齊
來(lái)舉一個(gè)最簡(jiǎn)單的例子吧,請(qǐng)看截圖
例題a
這個(gè)int 類型數(shù)據(jù)占據(jù)四個(gè)存儲(chǔ)單元是 0~ 3(四個(gè)字節(jié)),但由于double 是8個(gè)字節(jié),根據(jù)準(zhǔn)則a,那么我們需要填充四個(gè)字節(jié),從存儲(chǔ)單元8開始填double b,即存儲(chǔ)單元8~15是b的數(shù)據(jù),所以存儲(chǔ)單元0 ~15是16個(gè)字節(jié)
例題b
此例題說(shuō)明 準(zhǔn)則二 和準(zhǔn)則三的作用
在對(duì)象bq中,有 int a,double aa,char c,根據(jù)三準(zhǔn)則中準(zhǔn)則一,首先int a占 4字節(jié)(存儲(chǔ)單元0 ~ 3);然后根據(jù)準(zhǔn)則二 double aa 排列的存儲(chǔ)單元是 8 ~ 15,char c排列的存儲(chǔ)單元是 16;根據(jù)準(zhǔn)則三收尾功能填充,則對(duì)象bq占了24字節(jié)(最后0 ~ 23占了24個(gè)字節(jié));
然后da對(duì)象中,有 char aa ,b a,int aaa,根據(jù)三準(zhǔn)則中準(zhǔn)則一,首先char aa 占一字節(jié)(存儲(chǔ)單元0);然后 根據(jù)準(zhǔn)則二b a排列的存儲(chǔ)單元是 8 ~ 31,int aaa排列的存儲(chǔ)單元是32~35;根據(jù)準(zhǔn)則三收尾功能,填充36 ~39(最后0 ~ 39占了40個(gè)字節(jié));
提示:當(dāng)結(jié)構(gòu)體中以數(shù)組作為成員時(shí),將根據(jù)數(shù)組元素的長(zhǎng)度計(jì)算對(duì)齊值,而不是按數(shù)組的整體大小去計(jì)算,例題如下:
例題c
解釋:
在對(duì)象bq中,有double a[2],int aa,char c,根據(jù)三準(zhǔn)則中準(zhǔn)則一,首先double a[2]占 16字節(jié)(存儲(chǔ)單元0 ~ 15);然后根據(jù)準(zhǔn)則一 int aa 排列的存儲(chǔ)單元是 16 ~ 19,char c排列的存儲(chǔ)單元是 20;根據(jù)準(zhǔn)則三收尾功能填充,在這里我們需要討論了,如果用double 數(shù)組總長(zhǎng)度來(lái)帶入準(zhǔn)則三的話,那么應(yīng)該為32,所以此排除;如果用double單個(gè)元素的長(zhǎng)度來(lái)帶入準(zhǔn)則三的話,那么符合
當(dāng)然在這里還有同學(xué)肯定有疑問(wèn),如果我以 int aa 帶入準(zhǔn)則三呢?(因?yàn)閿?shù)組這種東西比較特殊,跟其它的有點(diǎn)不一樣,萬(wàn)一特殊呢?對(duì)吧?)
所以的話,我已經(jīng)準(zhǔn)備好下面的東西來(lái)解釋了
哎呀,把int aa改成了char aa,還是24呀,那么是不是就驗(yàn)證了我的說(shuō)法呢?
好啦,這里告一段落,給大家來(lái)個(gè)題目,下面會(huì)輸出什么呢?
class b {double a; char c; }; void main() {b bq;int lengthbq = sizeof(bq); cout << lengthbq #pragma pack(N)用法如下所示:
VC++6.0 中可使用預(yù)編譯指令#pragma pack(N)來(lái)調(diào)整對(duì)齊大小,當(dāng)上面把對(duì)齊值改過(guò)后,它并非原來(lái)的16字節(jié),而是變成9字節(jié)。
使用pack修改對(duì)齊值也并非一定會(huì)生效,與默認(rèn)對(duì)齊值一樣,對(duì)需要參考結(jié)構(gòu)體中數(shù)據(jù)成員類型。當(dāng)設(shè)定的對(duì)齊值大于結(jié)構(gòu)體中的數(shù)據(jù)成員類型大小時(shí),此對(duì)齊值是無(wú)效的。對(duì)齊值的計(jì)算流程換種說(shuō)法是:將設(shè)定的對(duì)齊值與結(jié)構(gòu)體中最大的基本類型數(shù)據(jù)成員的長(zhǎng)度進(jìn)行比較,取兩者之間的較小值。
如下
驗(yàn)證以上說(shuō)法
總結(jié)
以上是生活随笔為你收集整理的c++对象长度之内存对齐(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2020-11-27(switch的优化
- 下一篇: 字符常量在C和C++中的区别