• <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)體對齊那點事 熟練c/c++(四)

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

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

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

                  struct example1{

                       char a;

                       double b;

                       long l;

            };

                  struct example2{

                       char a;

                       long l;

                       double b;

            };

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

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

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

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

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

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

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

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

                  1.確定按照幾對齊: 16;

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

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

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

                 再舉個結(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)

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

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


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

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

            評論

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            謝謝你的提醒,我改好了,呵呵
            2010-01-14 23:24 | 攀升
            一本久久久久久久| 久久香蕉综合色一综合色88| 久久高清一级毛片| 伊人久久大香线蕉综合网站| 久久精品aⅴ无码中文字字幕不卡| 午夜精品久久久久久| 色欲久久久天天天综合网精品 | 亚洲日本va中文字幕久久| 久久夜色精品国产噜噜噜亚洲AV| 久久国产精品久久久| 亚洲欧洲精品成人久久曰影片 | 99久久精品免费看国产免费| 日产久久强奸免费的看| AAA级久久久精品无码片| 性高湖久久久久久久久AAAAA| 国产精品久久久久久吹潮| 最新久久免费视频| 精品国产婷婷久久久| 久久se精品一区精品二区| 中文精品99久久国产| 麻豆精品久久精品色综合| 少妇人妻88久久中文字幕| 久久久青草青青国产亚洲免观| 久久99精品久久久久子伦| 国产毛片欧美毛片久久久| 久久人人超碰精品CAOPOREN| 91精品国产91久久综合| 99精品国产99久久久久久97| 久久久久久久国产免费看| 色偷偷888欧美精品久久久| 久久久无码一区二区三区| 少妇无套内谢久久久久| 色老头网站久久网| 区久久AAA片69亚洲| 久久综合久久综合亚洲| 四虎国产精品成人免费久久| 欧美国产精品久久高清| 无码人妻少妇久久中文字幕| 一级做a爰片久久毛片免费陪 | 无码AV中文字幕久久专区| 色欲久久久天天天综合网|