• <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>

            攀升·Uranus


            Something Different,Something New
            數(shù)據(jù)加載中……

            結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)

                      剛剛完成一個(gè)文件的遷移程序,其中遇到了結(jié)構(gòu)體對(duì)齊的問題,所以拿出來說說,與各位博友們分享。

            我的程序很簡(jiǎn)單,就是把之前通過一個(gè)結(jié)構(gòu)體fwrite到文件A里的內(nèi)容讀出,然后轉(zhuǎn)給另一個(gè)結(jié)構(gòu)體保存。程序是簡(jiǎn)單,但我擔(dān)心的是之前結(jié)構(gòu)體fwrite到文件A的程序?qū)R結(jié)構(gòu)體規(guī)則是怎樣的?一定要知道它嗎? 當(dāng)然了,如果那個(gè)程序結(jié)構(gòu)體是按照1對(duì)齊寫入的,我的程序結(jié)構(gòu)體是按照4對(duì)齊讀入,那不就糟了!

                  這里我引入結(jié)構(gòu)體對(duì)齊的概念,也可以說是內(nèi)存對(duì)齊了。為什么要內(nèi)存對(duì)齊呢,就是方便CPU尋址了,具體原因大家要參考計(jì)算機(jī)體系結(jié)構(gòu)了。先看一個(gè)內(nèi)存對(duì)齊的例子:

                  struct example1{

                       char a;

                       double b;

                       long l;

            };

                  struct example2{

                       char a;

                       long l;

                       double b;

            };

            大家算算結(jié)構(gòu)體大小,初次接觸的博友可能對(duì)答案有點(diǎn)驚訝,VC編譯, sizeof后結(jié)果分別是:2416 同樣是的結(jié)構(gòu)體,成員換了順序,大小就不同了。其實(shí)內(nèi)存對(duì)齊有個(gè)規(guī)則,只要知道了,就OK。那么以下5點(diǎn)是關(guān)鍵

            1.          內(nèi)存對(duì)齊與編譯器設(shè)置有關(guān),首先要搞清編譯器這個(gè)默認(rèn)值是多少

            2.          如果不想編譯器默認(rèn)的話,可以通過#pragma pack(n)來指定按照n對(duì)齊

            3.          每個(gè)結(jié)構(gòu)體變量對(duì)齊,如果對(duì)齊參數(shù)n(編譯器默認(rèn)或者通過pragma指定)大于該變量所占字節(jié)數(shù)(m),那么就按照m對(duì)齊,內(nèi)存偏移后的地址是m的倍數(shù),否則是按照n對(duì)齊,內(nèi)存偏移后的地址是n的倍數(shù)。也就是最小化長(zhǎng)度規(guī)則

            4.          結(jié)構(gòu)體總大小: 對(duì)齊后的長(zhǎng)度必須是成員中最大的對(duì)齊參數(shù)的整數(shù)倍。最大對(duì)齊參數(shù)是從第三步得到的。

            5.          補(bǔ)充:如果結(jié)構(gòu)體A中還要結(jié)構(gòu)體B,那么B的對(duì)齊方式是選它里面最長(zhǎng)的成員的對(duì)齊方式

            所以計(jì)算結(jié)構(gòu)體大小要走三步,首先確定是當(dāng)前程序按照幾對(duì)齊(參照12點(diǎn)),接著計(jì)算每個(gè)結(jié)構(gòu)體變量的大小和偏移(參照35),最后計(jì)算結(jié)構(gòu)體總大小(參照4)。

                  先算算example1吧,假設(shè)編譯器是以16對(duì)齊的

                  1.確定按照幾對(duì)齊: 16;

                  2.確定每個(gè)成員的偏移:a 占一個(gè)字節(jié),16>1, 按照1對(duì)齊,起始位置00%1 = 0,那么a就存在0位置;b8個(gè)字節(jié),16>8,按照8對(duì)齊,起始位置就不能是1了,因?yàn)橐凑?/span>8對(duì)齊,所以最近的偏移起始位置是8 8%8 =0, 那么b就存在位置8-15的位置;l4個(gè)字節(jié),16>4,按照4對(duì)齊,起始位置16 16%4=0,那么l就存在位置16-19的位置。所以結(jié)構(gòu)體從019一共占用20個(gè)字節(jié)

                  3.結(jié)構(gòu)體總大小:成員中最大的對(duì)齊參數(shù)是b8對(duì)齊,所以208!=0, 24剛好。

                  真的很搞!同理計(jì)算example2應(yīng)該是16

                 再舉個(gè)結(jié)構(gòu)體嵌套的例子吧,

            #pragma pack(push)

            #pragma pack(8)

            struct test1{

                  int a;

                  char b;

                  int c[20]

            long l;

            } ;

            struct test2{

                  char a1;

                  char a2;

                  struct test1 t1;

                  double b1;

            }

            #pragma pack(pop)

            先計(jì)算test1, 8對(duì)齊,a占用0-3b占用4c占用887l占用8891,一共92個(gè)字節(jié)。成員中最大的對(duì)齊參數(shù)是int92%4=0;

            再計(jì)算test2, a1z占用0a2占用1t1呢,4 % 4 (test1里面最長(zhǎng)的成員的對(duì)齊方式) = 0, 4-95b196103;一共104個(gè)字節(jié),成員中最大的對(duì)齊參數(shù)是double104%8=0; 所以是104.


                  那關(guān)于我文章開頭提到的那個(gè)文件轉(zhuǎn)換,我現(xiàn)在只要知道原始程序是按照什么對(duì)齊的,然后在新程序中指定按照幾對(duì)齊就可以了,哈哈!            
                  
                  擠時(shí)間寫的,
            有的地方有遺漏,請(qǐng)各位指正!

            posted on 2009-01-06 23:39 攀升 閱讀(8859) 評(píng)論(9)  編輯 收藏 引用 所屬分類: C/C++

            評(píng)論

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            恩. 很有道理
            2009-01-07 11:13 | li_young

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            在gcc下example1和example2都是16
            2009-01-07 12:53 | ronliu

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            在gcc下example1和example2都是16 中默認(rèn)字節(jié)對(duì)齊為4 所以都是16
            2009-01-07 16:57 | feosun

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            @ronliu
            博友feosun告訴了你答案
            所以為了防止不同編譯器對(duì)齊不一樣,我建議在代碼里面指定對(duì)齊參數(shù)
            #pragma pack(n)
            2009-01-07 18:14 | 攀升

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            內(nèi)存對(duì)齊一直是很熱的話題啊。。呵呵。。。
            2009-01-08 08:38 | guest

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            有個(gè)地方?jīng)]太看懂
            就是嵌套結(jié)構(gòu)體時(shí),如何決定嵌套結(jié)構(gòu)體的首地址?即文中"t1呢,92%2!=0, 2-92"這一段,不是說考慮結(jié)構(gòu)體大小時(shí),應(yīng)該為其成員的最大值么?
            2009-08-31 10:54 | 游客

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            能否把我給你的評(píng)論(最前面的兩條中有)刪掉,我的留言中使用了郵件地址,收到了無數(shù)的垃圾郵件,煩都煩死了。如果可以,真的不勝感激
            2009-10-16 22:09 | 你好!

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            @你好!
            我?guī)湍闾幚砹耍?
            2010-01-14 23:12 | 攀升

            # re: 結(jié)構(gòu)體對(duì)齊那點(diǎn)事 熟練c/c++(四)   回復(fù)  更多評(píng)論   

            @游客
            >有個(gè)地方?jīng)]太看懂
            >就是嵌套結(jié)構(gòu)體時(shí),如何決定嵌套結(jié)構(gòu)體的首地址?即文中"t1呢,92%2!>=0, 2-92"這一段,不是說考慮結(jié)構(gòu)體大小時(shí),應(yīng)該為其成員的最大值么?

            謝謝你的提醒,我改好了,呵呵
            2010-01-14 23:24 | 攀升
            无夜精品久久久久久| 亚洲狠狠婷婷综合久久蜜芽| 国产精品久久新婚兰兰| 亚洲国产精品久久久久网站| 国产欧美一区二区久久| 国产产无码乱码精品久久鸭| 人妻无码久久一区二区三区免费| 99精品久久精品一区二区| 久久亚洲精品国产精品婷婷| 久久婷婷国产剧情内射白浆 | 久久亚洲精品成人AV| 区久久AAA片69亚洲| 性做久久久久久久| 色欲av伊人久久大香线蕉影院| 亚洲国产精品久久久天堂| 亚洲中文字幕无码一久久区| 99久久99久久精品免费看蜜桃| 久久精品国产亚洲一区二区| 狠狠精品久久久无码中文字幕| 欧美亚洲另类久久综合婷婷 | 综合久久国产九一剧情麻豆| 国产色综合久久无码有码| 久久夜色精品国产噜噜麻豆| 久久亚洲高清观看| 久久99热这里只有精品66| 一本一本久久A久久综合精品| WWW婷婷AV久久久影片| 久久天天日天天操综合伊人av| 色妞色综合久久夜夜| 久久99热精品| 久久中文字幕人妻熟av女| 久久99精品国产自在现线小黄鸭| 51久久夜色精品国产| 亚洲欧美成人综合久久久| 亚洲国产精品久久久久网站| 久久久久亚洲AV片无码下载蜜桃| 国内精品九九久久久精品| 亚洲国产精品无码久久青草| 亚洲va久久久噜噜噜久久| 精品久久久久久无码人妻热| 久久久久久亚洲AV无码专区|