一江春水向東流

          做一個(gè)有思想的人,期待與每一位熱愛(ài)思考的人交流,您的關(guān)注是對(duì)我最大的支持。

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            44 隨筆 :: 139 文章 :: 81 評(píng)論 :: 0 Trackbacks
          #pragma pack() struct test { char m1; double m4; int m3; }; #pragma pack() #pragma pack(8) struct A { int n; char c; short s; }; struct B { char c; int n; short s; }; #pragma pack() sizeof test:16 sizeof a:8 sizeof b:12 編譯器默認(rèn)的成員對(duì)齊值是8字節(jié),通過(guò)#pragma pack(show)指令,編譯的時(shí)候在輸出欄會(huì)限制默認(rèn)對(duì)齊值。以上程序運(yùn)行完通過(guò)調(diào)試的內(nèi)存察看功能得到a和b的內(nèi)存存儲(chǔ)區(qū)域如下: a的存儲(chǔ)區(qū)域:0x0012FED0 02 00 00 00 31 00 03 00 b的存儲(chǔ)區(qū)域:0x0012FEBC 31 00 00 00 02 00 00 00 03 00 00 00 最前面的4字節(jié)整數(shù)是變量的起始地址,后面是變量的整個(gè)存儲(chǔ)區(qū)域。 現(xiàn)在我們按照 align of member = min( pack setting value, sizeof(member) )的公式分析一下a和b的存儲(chǔ)。 a的第一個(gè)成員n為int,大小為4,align of a.n = min(8,sizeof(int) ),對(duì)齊值為4。第一個(gè)成員相對(duì)于結(jié)構(gòu)體起始地址從0偏移開(kāi)始,前四個(gè)字節(jié)02 00 00 00即為n的存儲(chǔ)區(qū)域,因?yàn)閤86是Little Endian(低字節(jié)在前)的字節(jié)順序,所以第一字節(jié)是2,后面三個(gè)字節(jié)0,我們通常寫(xiě)成0x00000002; a的第二個(gè)成員c為char,大小為1,align of a.c=min(8,sizeof(char)),對(duì)齊值為1。c緊接著a后面存儲(chǔ)從偏移4開(kāi)始,滿(mǎn)足1字節(jié)對(duì)齊的要求。它的值為'1',ASCII碼為0x31,共一個(gè)字節(jié)31; a的第三個(gè)成員為short,大小為2,align of a.s=min(8,sizeof(short)),對(duì)齊值為2。如果緊接第二個(gè)成員從偏移5開(kāi)始存儲(chǔ)就不滿(mǎn)足2字節(jié)對(duì)齊,因此跳過(guò)1個(gè)字節(jié),從偏移6字節(jié)的地方開(kāi)始存儲(chǔ),即最后兩個(gè)字節(jié)03 00; b的第一個(gè)成員c為char,大小為1,align of a.c=min(8,sizeof(char)),對(duì)齊值為1。第一個(gè)成員從偏移起始地址0字節(jié)開(kāi)始存儲(chǔ),它的值為'1',ASCII碼為0x31,共一個(gè)字節(jié)31; b的第二個(gè)成員n為int,大小為4,align of a.n = min(8,sizeof(int) ),對(duì)齊值為4。如果緊接第二個(gè)成員后面從偏移1開(kāi)始存儲(chǔ)就不能4字節(jié)對(duì)齊,因此跳過(guò)3個(gè)字節(jié),從偏移4字節(jié)的地方開(kāi)始存儲(chǔ),即第5-8的四個(gè)字節(jié)02 00 00 00; b的第三個(gè)成員為short,大小為2,align of a.s=min(8,sizeof(short)),對(duì)齊值為2。緊接第二個(gè)成員從偏移8字節(jié)的地方開(kāi)始存儲(chǔ),即9-10兩個(gè)字節(jié)03 00; 這時(shí)有人可能要問(wèn),b為什么最后多了兩個(gè)字節(jié)00 00呢?這就是我們下面要講的,整個(gè)結(jié)構(gòu)體的對(duì)齊。 2、align指令 align指令可以用于設(shè)置各種內(nèi)置類(lèi)型、自定義類(lèi)型如struct、union或class的的對(duì)齊方式。指令格式為:__declspec(align(#)) ,#是對(duì)齊值,取值為2的1次方至2的8192次方。在聲明自定義類(lèi)型或內(nèi)置變量時(shí),如果指定了對(duì)齊值,則對(duì)應(yīng)變量的起始地址必須是該值的整數(shù)倍。除此外,它還會(huì)影響結(jié)構(gòu)體的大小。下面引用兩段MSDN關(guān)于align的描述: Without __declspec(align(#)), Visual C++ aligns data on natural boundaries based on the size of the data, for example 4-byte integers on 4-byte boundaries and 8-byte doubles on 8-byte boundaries. Data in classes or structures is aligned within the class or structure at the minimum of its natural alignment and the current packing setting (from #pragma pack or the /Zp compiler option). 從這段可以看出,如果沒(méi)有設(shè)置align(#)值,變量x按照sizeof(x)來(lái)對(duì)齊起始地址。類(lèi)或結(jié)構(gòu)體內(nèi)的成員在類(lèi)或結(jié)構(gòu)體內(nèi)部按照min( pack setting value,sizeof(member))來(lái)對(duì)齊。這個(gè)我們?cè)趐ack指令部分已經(jīng)分析過(guò)。 The sizeof value for any structure is the offset of the final member, plus that member's size, rounded up to the nearest multiple of the largest member alignment value or the whole structure alignment value, whichever is greater. 從這段可以看出,align(#)指令會(huì)影響結(jié)構(gòu)體或類(lèi)的大小。總結(jié)公式為: sizeof(structure) = (結(jié)構(gòu)體最后一個(gè)成員的偏移 + sizeof(結(jié)構(gòu)體最后一個(gè)成員) ) 上取整 ( n* max( 結(jié)構(gòu)體各成員的對(duì)齊值,align(#)設(shè)置的值 ) ); 其中n為正整數(shù)。 根據(jù)該公式我們分析一下b為什么后面會(huì)多兩個(gè)填充字節(jié)0。 b的最后一個(gè)成s偏移為8,大小為2,b中各成員對(duì)齊值最大的為4,因?yàn)槲丛O(shè)置align(#),所以上取整的數(shù)值為4n。8+2按4的倍數(shù)上取整為12。因此后面需要填充兩個(gè)字節(jié),這樣才能使sizeof(b) == 12。
          posted on 2012-06-05 18:00 allic 閱讀(376) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): C/C++
          主站蜘蛛池模板: 赤峰市| 股票| 西宁市| 武鸣县| 台北县| 雷山县| 水富县| 平果县| 德安县| 太谷县| 佛山市| 平定县| 清丰县| 佛学| 夏津县| 玛多县| 铜陵市| 宜川县| 南通市| 原阳县| 西安市| 阿克陶县| 耿马| 永清县| 仙游县| 大冶市| 资中县| 喜德县| 察隅县| 碌曲县| 平罗县| 边坝县| 兴文县| 六枝特区| 晋宁县| 五华县| 雷州市| 呼和浩特市| 莒南县| 彰化市| 光山县|