• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            franksunny的個(gè)人技術(shù)空間
            獲得人生中的成功需要的專注與堅(jiān)持不懈多過(guò)天才與機(jī)會(huì)。 ——C.W. Wendte

            由一道面試題來(lái)看 Struct 的對(duì)界

             

            本文節(jié)選自宋寶華的C/C++struct深層探索一文,本人對(duì)其所描述的struct對(duì)齊比較喜歡,為此轉(zhuǎn)來(lái)與大家分享,原文見(jiàn)http://blog.donews.com/21cnbao/archive/2005/09/08/544877.aspx

             

            Intel 、微軟等公司曾經(jīng)出過(guò)一道類似的面試題:

            1. #include <iostream.h>

            2. #pragma pack(8)

            3. struct example1

            4. {

            5.     short a;

            6.     long b;

            7. };

            8. struct example2

            9. {

            10.          char c;

            11.          example1 struct1;

            12.          short e;

            13. };

            14. #pragma pack()

             

            15. int main(int argc, char* argv[])

            16. {

            17.          example2 struct2;

            18.   cout << sizeof(example1) << endl;

            19.   cout << sizeof(example2) << endl;

            20.   cout << (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2)

            << endl;

            21. return 0;

            22. }

            問(wèn)程序的輸入結(jié)果是什么?

            答案是:

            8

            16

            4

            不明白?還是不明白?下面一一道來(lái):

            1 自然對(duì)界

            struct 是一種復(fù)合數(shù)據(jù)類型,其構(gòu)成元素既可以是基本數(shù)據(jù)類型(如 int long 、 float 等)的變量,也可以是一些復(fù)合數(shù)據(jù)類型(如 array 、 struct 、 union 等)的數(shù)據(jù)單元。對(duì)于結(jié)構(gòu)體,編譯器會(huì)自動(dòng)進(jìn)行成員變量的對(duì)齊,以提高運(yùn)算效率。缺省情況下,編譯器為結(jié)構(gòu)體的每個(gè)成員按其自然對(duì)界( natural alignment )條件分配空間。各個(gè)成員按照它們被聲明的順序在內(nèi)存中順序存儲(chǔ),第一個(gè)成員的地址和整個(gè)結(jié)構(gòu)的地址相同。

            自然對(duì)界 (natural alignment) 即默認(rèn)對(duì)齊方式,是指按結(jié)構(gòu)體的成員中 size 最大的成員對(duì)齊。

            例如:

            struct naturalalign

            {

            char a;

            short b;

            char c;

            };

            在上述結(jié)構(gòu)體中, size 最大的是 short ,其長(zhǎng)度為 2 字節(jié),因而結(jié)構(gòu)體中的 char 成員 a c 都以 2 為單位對(duì)齊, sizeof(naturalalign) 的結(jié)果等于 6 ;

            如果改為:

            struct naturalalign

            {

            char a;

            int b;

            char c;

            };

            其結(jié)果顯然為 12 。

             

            2 指定對(duì)界

            一般地,可以通過(guò)下面的方法來(lái)改變?nèi)笔〉膶?duì)界條件:

            · 使用偽指令 #pragma pack (n) ,編譯器將按照 n 個(gè)字節(jié)對(duì)齊;

            · 使用偽指令 #pragma pack () ,取消自定義字節(jié)對(duì)齊方式。

            注意:如果 #pragma pack (n) 中指定的 n 大于結(jié)構(gòu)體中最大成員的 size ,則其不起作用,結(jié)構(gòu)體仍然按照 size 最大的成員進(jìn)行對(duì)界。

            例如:

            #pragma pack (n)

            struct naturalalign

            {

            char a;

            int b;

            char c;

            };

            #pragma pack ()

            當(dāng) n 4 8 16 時(shí),其對(duì)齊方式均一樣, sizeof(naturalalign) 的結(jié)果都等于 12 。而當(dāng) n 2 時(shí),其發(fā)揮了作用,使得 sizeof(naturalalign) 的結(jié)果為 8 。

            VC++ 6.0 編譯器中,我們可以指定其對(duì)界方式(見(jiàn)圖 1 ),其操作方式為依次選擇 projetct > setting > C/C++ 菜單,在 struct member alignment 中指定你要的對(duì)界方式。

            1  在 VC++ 6.0 中指定對(duì)界方式

            另外,通過(guò) __attribute((aligned (n))) 也可以讓所作用的結(jié)構(gòu)體成員對(duì)齊在 n 字節(jié)邊界上,但是它較少被使用,因而不作詳細(xì)講解。

             

            3 、   面試題的解答

            至此,我們可以對(duì) Intel 、微軟的面試題進(jìn)行全面的解答。

            程序中第 2 #pragma pack (8) 雖然指定了對(duì)界為 8 ,但是由于 struct example1 中的成員最大 size 4 long 變量 size 4 ),故 struct example1 仍然按 4 字節(jié)對(duì)界, struct example1 size 8 ,即第 18 行的輸出結(jié)果;

            struct example2 中包含了 struct example1 ,其本身包含的簡(jiǎn)單數(shù)據(jù)成員的最大 size 2 short 變量 e ),但是因?yàn)槠浒?/span> struct example1 ,而 struct example1 中的最大成員 size 4 , struct example2 也應(yīng)以 4 對(duì)界, #pragma pack (8) 中指定的對(duì)界對(duì) struct example2 也不起作用,故 19 行的輸出結(jié)果為 16 ;

            由于 struct example2 中的成員以 4 為單位對(duì)界,故其 char 變量 c 后應(yīng)補(bǔ)充 3 個(gè)空,其后才是成員 struct1 的內(nèi)存空間, 20 行的輸出結(jié)果為 4 。

             

             

            在閱讀了此節(jié)之后,本人對(duì)為什么在使用過(guò)程中用sizeof取得的結(jié)構(gòu)長(zhǎng)度不同的問(wèn)題有了認(rèn)識(shí),不過(guò)本人調(diào)試時(shí),不光跟對(duì)界方式有關(guān),還和設(shè)置的Processor有關(guān),這方面還請(qǐng)大俠幫我指點(diǎn)下迷津。

                過(guò)了快一年了,回過(guò)頭來(lái)再看看這篇文章發(fā)現(xiàn)還是有用的,另外再加上一句別人:當(dāng)未用 #pragma 指令指定編譯器的對(duì)齊位數(shù)時(shí),結(jié)構(gòu)體按最長(zhǎng)寬度的數(shù)據(jù)成員的寬度對(duì)齊;當(dāng)使用了#pragma 指令指定編譯器的對(duì)齊位數(shù)時(shí),結(jié)構(gòu)體按最長(zhǎng)寬度的數(shù)據(jù)成員的寬度和 #pragma 指令指定的位數(shù)中的較小值對(duì)齊。(2007年10月8日) 

            posted on 2006-10-20 21:52 frank.sunny 閱讀(2101) 評(píng)論(9)  編輯 收藏 引用 所屬分類: C/C++學(xué)習(xí)和實(shí)踐

            FeedBack:
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2006-12-22 13:32 | mumutou
            錯(cuò)誤,struct所說(shuō)的對(duì)齊不是這么回事
              回復(fù)  更多評(píng)論
              
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2006-12-22 13:34 | mumutou
            char a;

            int b;

            char c;
            按照4邊界對(duì)齊,1+4+1 =6;
            (6/4+1) * 4 = 8
            也就是說(shuō)對(duì)struct總的長(zhǎng)度進(jìn)行4邊界對(duì)齊,而不是對(duì)每個(gè)struct內(nèi)容4邊界對(duì)齊  回復(fù)  更多評(píng)論
              
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2006-12-26 20:59 | frank.sunny
            謝謝樓上的大俠提點(diǎn),在你的指點(diǎn)下,認(rèn)真看了下對(duì)齊的東西,你說(shuō)的也不是很對(duì)
            上面的題按4邊界對(duì)齊的話,也要考慮順序的即 1+(3)+ 4 + 1 = 9
            (9 / 4 +1) * 4 = 12
            也就前一個(gè)類型根據(jù)后一個(gè)類型擴(kuò)展
            具體我再附上別人的源代碼。

            struct DATA1
            {
            char c1; //偏移量0,累積size = 1
            char c2; //偏移量1,累積size = 1 + 1 = 2
            short si; //偏移量2,累積size = 2 + 2
            };

            struct DATA2
            {
            char c1; //偏移量0,累積size = 1
            short si; //偏移量1 + (1),累積size = 1 + (1) + 2 = 4
            char c2; //偏移量4,累積size = 4 + 1 = 5,但按最大長(zhǎng)度sizeof(short) = 2對(duì)齊,故最后取6
            };

            struct DATA3
            {
            char c1; //偏移量0,累積size = 1
            double d; //偏移量1 + (7),累積size = 1 + (7) + 8 = 16
            char c2; //偏移量16,累積size = 16 + 1 = 17,但按最大長(zhǎng)度sizeof(double) = 8對(duì)齊,故最后取24
            };

            #pragma pack(push,1) //強(qiáng)制1字節(jié)對(duì)齊
            struct DATA4
            {
            char c1; //偏移量0,累積size = 1
            double d; //偏移量1,累積size = 1 + 8 = 9
            char c2; //偏移量9,累積size = 9 + 1 = 10
            };
            #pragma pack(pop) //恢復(fù)默認(rèn)對(duì)齊方式

            struct DATA5
            {
            char c1;
            double d;
            char c2;
            };

            void main()
            {
            cout << "sizeof(DATA1) = " << sizeof(DATA1) << endl;
            cout << "sizeof(DATA2) = " << sizeof(DATA2) << endl;
            cout << "sizeof(DATA3) = " << sizeof(DATA3) << endl;
            cout << "sizeof(DATA4) = " << sizeof(DATA4) << endl;
            cout << "sizeof(DATA5) = " << sizeof(DATA5) << endl;
            }  回復(fù)  更多評(píng)論
              
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2008-07-18 11:37 | dshy
            struct test {
            char x1;
            short x2;
            float x3;
            char x4;
            };

            sizeof(test)是多少?  回復(fù)  更多評(píng)論
              
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2009-03-04 17:59 | JYSG3
            錯(cuò)誤,誤人子弟  回復(fù)  更多評(píng)論
              
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2009-03-18 16:12 | 撒旦
            sizeof(test)是多少?
            //應(yīng)該是12個(gè)字節(jié)吧,1 + 2 + (1) + 4 +1 =9,因?yàn)槭且?字節(jié)對(duì)起,所以應(yīng)該是12字節(jié)。  回復(fù)  更多評(píng)論
              
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2010-04-24 11:43 | 小林
            您好: 我讀了你的代碼分析,收獲頗多。也發(fā)現(xiàn)了一點(diǎn)小問(wèn)題,現(xiàn)向你提一下。
            我將你的程序在機(jī)子上運(yùn)行,發(fā)現(xiàn)你的分析結(jié)果跟電腦顯示的結(jié)果不一樣。
            double,long 最大長(zhǎng)度不是按8 對(duì)齊,而是 按4對(duì)齊。
            struct DATA3
            {
            char c1; //偏移量0,累積size = 1
            double d; //偏移量1 + (3),累積size = 1 + (3) + 8 = 112
            char c2; //偏移量16,累積size = 12+ 1 = 13,但按最大長(zhǎng)度sizeof(double) = 4對(duì)齊,故最后取16
            };   回復(fù)  更多評(píng)論
              
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2011-03-16 13:53 | casper
            路過(guò),學(xué)習(xí),有問(wèn)題:
            struct DATA3
            {
            char c1; //偏移量0,累積size = 1
            double d; //偏移量1 + (7),累積size = 1 + (7) + 8 = 16
            char c2; //偏移量16,累積size = 16 + 1 = 17,但按最大長(zhǎng)度sizeof(double) = 8對(duì)齊,故最后取24
            };
            就拿這個(gè)來(lái)說(shuō) 這個(gè)的結(jié)果應(yīng)該是16

            不能用單獨(dú)的最長(zhǎng)來(lái)界定

            單個(gè)的元素需要在結(jié)構(gòu)體內(nèi)部對(duì)齊

            同時(shí)最后還需要界定整個(gè)結(jié)構(gòu)體的對(duì)齊問(wèn)題  回復(fù)  更多評(píng)論
              
            # re: 由一道面試題來(lái)看Struct的對(duì)界(再談結(jié)構(gòu))
            2011-03-16 14:03 | casper
            struct DATA3{
            char c1;
            double d;
            char c2;
            };
            *結(jié)構(gòu)體內(nèi)部 有補(bǔ)齊需求的只有d
            sizeof(double) > 4 ---> 4
            c1 block 1+(3)=4
            total: 1+(3)+8+1=13
            *結(jié)構(gòu)體開始對(duì)齊
            sizeof(double) > 4 ---> 4 4*4-3=13
            c2 block 1+(3)=4
            total: 1+(3)+8+1+(3)=16@casper
              回復(fù)  更多評(píng)論
              

            常用鏈接

            留言簿(13)

            隨筆分類

            個(gè)人其它博客

            基礎(chǔ)知識(shí)鏈接

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久亚洲日韩精品一区二区三区| 一本一本久久A久久综合精品| 久久综合亚洲色HEZYO社区| 中文字幕久久欲求不满| 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 欧美丰满熟妇BBB久久久| 亚洲七七久久精品中文国产| 精品国产婷婷久久久| 久久精品无码一区二区三区| 久久99国产精品99久久| 日韩欧美亚洲综合久久影院d3| 久久精品国产网红主播| 精品免费久久久久久久| 国产美女久久精品香蕉69| 大伊人青草狠狠久久| 国产成人久久AV免费| 久久精品国产亚洲一区二区| 日本福利片国产午夜久久| 久久精品国内一区二区三区| 亚洲国产精品久久久久婷婷软件 | 久久无码AV中文出轨人妻| 久久久久噜噜噜亚洲熟女综合| 久久无码国产| 精品人妻伦九区久久AAA片69| 丁香色欲久久久久久综合网| 久久精品无码专区免费青青| 久久综合丁香激情久久| 久久男人AV资源网站| 久久只有这里有精品4| 伊人久久大香线蕉AV色婷婷色| 99久久国产热无码精品免费 | 人妻精品久久久久中文字幕| 伊人色综合九久久天天蜜桃| 亚洲国产精品18久久久久久| 99久久99这里只有免费的精品| 激情综合色综合久久综合| 久久只有这精品99| AV狠狠色丁香婷婷综合久久| 久久久久噜噜噜亚洲熟女综合| 色欲av伊人久久大香线蕉影院| 狠狠狠色丁香婷婷综合久久五月 |