字节对齐《c和指针》笔记--包含位域结构体的内存对齐(32bit,GCC)
最近使用開(kāi)發(fā)的過(guò)程中出現(xiàn)了一個(gè)小問(wèn)題,順便記錄一下原因和方法--字節(jié)對(duì)齊
????C99劃定int、unsigned ? int和bool可以作為位域類(lèi)型。但編譯器幾乎都對(duì)此作了擴(kuò)展,答應(yīng)其它類(lèi)型類(lèi)型的存在。
????如果結(jié)構(gòu)體中含有位域(bit-field),總結(jié)規(guī)則如下:(以下代碼在x86 32bit系統(tǒng)上測(cè)試,gcc 4.1.2)
????1) 如果相鄰位域字段的類(lèi)型相同,且其位寬之和小于類(lèi)型的sizeof巨細(xì),則前面的字段將緊鄰前一個(gè)字段存儲(chǔ),直到不能包容為止
????例:
????struct test1 {
? ? char ? ?a : 2;
? ? char ? ?b : 3;
? ? char ? ?c : 3;
????};
????3個(gè)變量恰好占1個(gè)字節(jié),所以整體只要占1個(gè)字節(jié)
????2) 如果相鄰位域字段的類(lèi)型相同,但其位寬之和大于類(lèi)型的sizeof巨細(xì),則前面的字段將從新的存儲(chǔ)單元開(kāi)始,其偏移量為其類(lèi)型巨細(xì)的整數(shù)倍
????例:
????struct test2 {
? ? char ? ?a : 2;
? ? char ? ?b : 3;
? ? char ? ?c : 7;
????};
????3個(gè)變量超過(guò)1個(gè)字節(jié),a和b在占一個(gè)字節(jié),c占一個(gè)字節(jié),所以整體占2個(gè)字節(jié)。
????3) 如果相鄰的位域字段的類(lèi)型不同,則各編譯器的詳細(xì)實(shí)現(xiàn)有差異,VC6采用不壓縮方法(不同位域字段存放在不同的位域類(lèi)型字節(jié)中),Dev-C++和GCC都采用壓縮方法
????例1:
????struct test3
????{
? ? char a:1;
? ? char b:1;
? ? long c:1;
? ? char d:2;
????};
????4個(gè)變量<=1個(gè)字節(jié),所以整體占1個(gè)字節(jié),對(duì)吧!
????錯(cuò)了,開(kāi)始我也是這樣想的,結(jié)果是4個(gè)。
????我猜想了一下:
????雖然a,b,c,d加起來(lái)只占1個(gè)字節(jié),但是最后結(jié)構(gòu)體整體也要停止對(duì)齊。
????詳細(xì)可以查看之前寫(xiě)的不含位域的內(nèi)存對(duì)齊說(shuō)明http://blog.csdn.net/todd911/article/details/6528428,
????對(duì)齊規(guī)則的第二條:結(jié)構(gòu)(或結(jié)合)的整體對(duì)齊規(guī)則:在 數(shù)據(jù)成員完成各自對(duì)齊之后,結(jié)構(gòu)(或結(jié)合)本身也要停止對(duì)齊,對(duì)齊將按照#pragma pack指定的數(shù)值和結(jié)構(gòu)(或結(jié)合)最大數(shù)據(jù)成員長(zhǎng)度中,比較小的那個(gè)停止。
每日一道理這濃濃的母愛(ài)使我深深地認(rèn)識(shí)到:即使你是一只矯健的雄鷹,也永遠(yuǎn)飛不出母愛(ài)的長(zhǎng)空;即使你是一條揚(yáng)帆行駛的快船,也永遠(yuǎn)駛不出母愛(ài)的長(zhǎng)河!在人生的路上不管我們已走過(guò)多遠(yuǎn),還要走多遠(yuǎn),我們都要經(jīng)過(guò)母親精心營(yíng)造的那座橋!
????這邊因?yàn)闆](méi)有定義#pragma pack,所以默認(rèn)按4個(gè)字節(jié)停止對(duì)齊,結(jié)構(gòu)體中最大的數(shù)是long,占4個(gè)字節(jié),所以最終要按4個(gè)字節(jié)停止整體對(duì)齊。
????我們來(lái)驗(yàn)證一下,如果將結(jié)構(gòu)體改成:
????struct test3
????{
? ? char ?a:1;
? ? char ?b:1;
? ? short c:1;
? ? char ?d:2;
????};
????結(jié)果應(yīng)該是2。
????試一下,確實(shí)是2.
????再來(lái)修改一下:
????struct test3
????{
? ? char a:1;
? ? char b:1;
? ? long c:31;
? ? char d:2;
????};
????上面的結(jié)構(gòu)體占12個(gè)字節(jié)。
????a,b合起來(lái)占1個(gè)字節(jié),c如果要合到a,b中去,的話(huà)就是33bit,超過(guò)將按照#pragma pack指定的數(shù)值和結(jié)構(gòu)(或結(jié)合)最大數(shù)據(jù)成員長(zhǎng)度中,比較小的那個(gè),
????所以c只能自立門(mén)戶(hù),從第5個(gè)字節(jié)(偏移量為32bit)開(kāi)始放置占4個(gè)字節(jié),同理最后d也合不進(jìn)c中去,所以從第9個(gè)字節(jié)開(kāi)始放置,最后結(jié)構(gòu)體整體對(duì)齊,結(jié)果是12.
????總結(jié)gcc的壓縮方法:
????a.先要取得#pragma pack指定的數(shù)值和結(jié)構(gòu)(或結(jié)合)最大數(shù)據(jù)成員長(zhǎng)度中,比較小的那個(gè)值,這邊稱(chēng)為對(duì)齊基數(shù)。
????b.按照結(jié)構(gòu)體中變量的次序,如果能合在一起且不超過(guò)a中的對(duì)齊基數(shù)的就合并,不能合并的需要自立門(mén)戶(hù),偏移量為對(duì)齊基數(shù)的整數(shù)倍,繼續(xù)檢查是否能停止合并。。。
????c.最后結(jié)構(gòu)體整體停止對(duì)齊。
????4)如果位域字段之間穿插著非位域字段,則不停止壓縮,按照不包含位域的結(jié)構(gòu)體停止對(duì)齊,詳細(xì)規(guī)則可以參考我以前寫(xiě)的文章:http://blog.csdn.net/todd911/article/details/6528428
????例:
????struct test4
????{
? ? char a:1;
? ? char b:1;
? ? short c;
? ? char d:1;
????};
????占用6個(gè)字節(jié)。
文章結(jié)束給大家分享下程序員的一些笑話(huà)語(yǔ)錄: 人在天涯鉆,哪兒能不挨磚?日啖板磚三百顆,不辭長(zhǎng)做天涯人~
總結(jié)
以上是生活随笔為你收集整理的字节对齐《c和指针》笔记--包含位域结构体的内存对齐(32bit,GCC)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: sql下员工工牌(YC0001)的简单实
- 下一篇: 关于Oracle数据库中行迁移/行链接的