


下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
解析C語言結(jié)構(gòu)體對齊(內(nèi)存對齊問題)C語言結(jié)構(gòu)體對齊也是老生常談的話題了?;旧鲜敲嬖囶}的必考題。內(nèi)容雖然很基礎(chǔ),但一不小心就會弄錯。寫出一個(gè)struct,然后sizeof,你會不會經(jīng)常對結(jié)果感到奇怪?sizeof的結(jié)果往往都比你聲明的變量總長度要大,這是怎么回事呢?
開始學(xué)的時(shí)候,也被此類問題困擾很久。其實(shí)相關(guān)的文章很多,感覺說清楚的不多。結(jié)構(gòu)體到底怎樣對齊?
有人給對齊原則做過總結(jié),具體在哪里看到現(xiàn)在已記不起來,這里引用一下前人的經(jīng)驗(yàn)(在沒有#pragmapack宏的情況下):
原則1、數(shù)據(jù)成員對齊規(guī)則:結(jié)構(gòu)(struct或聯(lián)合union)的數(shù)據(jù)成員,第一個(gè)數(shù)據(jù)成員放在offset為0的地方,以后每個(gè)數(shù)據(jù)成員存儲的起始位置要從該成員大小的整數(shù)倍開始(比如int在32位機(jī)為4字節(jié),則要從4的整數(shù)倍地址開始存儲)。
原則2、結(jié)構(gòu)體作為成員:如果一個(gè)結(jié)構(gòu)里有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開始存儲。(structa里存有structb,b里有char,int,double等元素,那b應(yīng)該從8的整數(shù)倍開始存儲。)
原則3、收尾工作:結(jié)構(gòu)體的總大小,也就是sizeof的結(jié)果,必須是其內(nèi)部最大成員的整數(shù)倍,不足的要補(bǔ)齊。
這三個(gè)原則具體怎樣理解呢?我們看下面幾個(gè)例子,通過實(shí)例來加深理解。
例1:struct{
shorta1;
shorta2;
shorta3;
}A;
struct{
longa1;
shorta2;
}B;
sizeof(A)=6;這個(gè)很好理解,三個(gè)short都為2。
sizeof(B)=8;這個(gè)比是不是比預(yù)想的大2個(gè)字節(jié)?long為4,short為2,整個(gè)為8,因?yàn)樵瓌t3。
例2:structA{
inta;
charb;
shortc;
};
structB{
charb;
inta;
shortc;
};
sizeof(A)=8;int為4,char為1,short為2,這里用到了原則1和原則3。
sizeof(B)=12;是否超出預(yù)想范圍?char為1,int為4,short為2,怎么會是12?還是原則1和原則3。
深究一下,為什么是這樣,我們可以看看內(nèi)存里的布局情況。
a
b
c
A的內(nèi)存布局:1111,
1*,
11
b
a
c
B的內(nèi)存布局:1***,
1111,
11**
其中星號*表示填充的字節(jié)。A中,b后面為何要補(bǔ)充一個(gè)字節(jié)?因?yàn)閏為short,其起始位置要為2的倍數(shù),就是原則1。c的后面沒有補(bǔ)充,因?yàn)閎和c正好占用4個(gè)字節(jié),整個(gè)A占用空間為4的倍數(shù),也就是最大成員int類型的倍數(shù),所以不用補(bǔ)充。
B中,b是char為1,b后面補(bǔ)充了3個(gè)字節(jié),因?yàn)閍是int為4,根據(jù)原則1,起始位置要為4的倍數(shù),所以b后面要補(bǔ)充3個(gè)字節(jié)。c后面補(bǔ)充兩個(gè)字節(jié),根據(jù)原則3,整個(gè)B占用空間要為4的倍數(shù),c后面不補(bǔ)充,整個(gè)B的空間為10,不符,所以要補(bǔ)充2個(gè)字節(jié)。
再看一個(gè)結(jié)構(gòu)中含有結(jié)構(gòu)成員的例子:
例3:structA{
inta;
doubleb;
floatc;
};
structB{
chare[2];
intf;
doubleg;
shorth;
structAi;
};
sizeof(A)=24;這個(gè)比較好理解,int為4,double為8,float為4,總長為8的倍數(shù),補(bǔ)齊,所以整個(gè)A為24。
sizeof(B)=48;看看B的內(nèi)存布局。
e
f
g
h
i
B的內(nèi)存布局:11**,
1111,
11111111,11******,
1111****,11111111,1111****
i其實(shí)就是A的內(nèi)存布局。i的起始位置要為24的倍數(shù),所以h后面要補(bǔ)齊。把B的內(nèi)存布局弄清楚,有關(guān)結(jié)構(gòu)體的對齊方式基本就算掌握了。
以上講的都是沒有#pragmapack宏的情況,如果有#pragmapack宏,對齊方式按照宏的定義來。比如上面的結(jié)構(gòu)體前加#pragmapack(1),內(nèi)存的布局就會完全改變。sizeof(A)=16;sizeof(B)=32;
有了#pragmapack(1),內(nèi)存不會再遵循原則1和原則3了,按1字節(jié)對齊。沒錯,這不是理想中的沒有內(nèi)存對齊的世界嗎。
a
b
c
A的內(nèi)存布局:1111,
11111111,
1111
e
f
g
h
i
B的內(nèi)存布局:11,
1111,
11111111,11,
1111,11111111,1111
那#pragmapack(2)的結(jié)果又是多少呢?#pragmapack(4)呢?留給大家自己思考吧,相信沒有問題。
還有一種常見的情況,結(jié)構(gòu)體中含位域字段。位域成員不能單獨(dú)被取sizeof值。C99規(guī)定int、unsignedint和bool可以作為位域類型,但編譯器幾乎都對此作了擴(kuò)展,允許其它類型類型的存在。
使用位域的主要目的是壓縮存儲,其大致規(guī)則為:
1)如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof大小,則后面的字段將緊鄰前一個(gè)字段存儲,直到不能容納為止;
2)如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字段將從新的存儲單元開始,其偏移量為其類型大小的整數(shù)倍;
3)如果相鄰的位域字段的類型不同,則各編譯器的具體實(shí)現(xiàn)有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式;
4)如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮;
5)整個(gè)結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍。
還是讓我們來看看例子。
例4:structA{
charf1:3;
charf2:4;
charf3:5;
};
a
b
c
A的內(nèi)存布局:111,
1111*,
11111***
位域類型為char,第1個(gè)字節(jié)僅能容納下f1和f2,所以f2被壓縮到第1個(gè)字節(jié)中,而f3只能從下一個(gè)字節(jié)開始。因此sizeof(A)的結(jié)果為2。
例5:structB{
charf1:3;
shortf2:4;
charf3:5;
};
由于相鄰位域類型不同,在VC6中其sizeof為6,在Dev-C++中為2。
例6:structC{
charf1:3;
charf2;
charf3:5;
};
非位域字段穿插在其中,不會產(chǎn)生壓縮,在VC6和Dev-C++中得到的大小均為3。
考慮一個(gè)問題,為什么要設(shè)計(jì)內(nèi)存對齊的處理方式呢?如果體系結(jié)構(gòu)是不對齊的,成員將會一個(gè)挨一個(gè)存儲,顯然對齊更浪費(fèi)了空間。那么為什么要使用對齊呢?體系結(jié)構(gòu)的對
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 勞動合同標(biāo)準(zhǔn)格式范文
- 簡易自愿離婚合同模板
- 菜鳥驛站快遞柜租賃合同
- 餐飲企業(yè)戰(zhàn)略合作區(qū)域代理合同樣本
- 老舊農(nóng)村房屋轉(zhuǎn)讓合同范本
- 自行車安全培訓(xùn)課件
- 木工機(jī)械的現(xiàn)代控制技術(shù)考核試卷
- 木質(zhì)游藝器材制作工藝考核試卷
- 批發(fā)行業(yè)的品牌形象塑造考核試卷
- 合成材料在汽車制造領(lǐng)域的應(yīng)用研究考核試卷
- 2024年云上貴州大數(shù)據(jù)(集團(tuán))有限公司招聘筆試沖刺題(帶答案解析)
- 珠海市高級技工學(xué)校校企合作管理辦法修訂
- GB 31825-2024制漿造紙單位產(chǎn)品能源消耗限額
- 消防設(shè)施操作員報(bào)名工作證明(操作員)
- 小學(xué)四年級心理健康教育課
- 供應(yīng)商開發(fā)流程及質(zhì)量要求
- 2024年技術(shù)監(jiān)督質(zhì)檢職業(yè)技能考試-電力技術(shù)監(jiān)督上崗員(中國華能)筆試歷年真題薈萃含答案
- 反假幣測試附有答案
- 怎樣調(diào)動員工積極性
- 2024年內(nèi)科護(hù)理學(xué)(第七版)期末考試復(fù)習(xí)題庫(含答案)
- 急診科培訓(xùn)急診科與其他科室的協(xié)作與溝通
評論
0/150
提交評論