青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

  C++博客 :: 首頁 :: 聯系 ::  :: 管理
  163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

常用鏈接

留言簿(48)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 402367
  • 排名 - 59

最新評論

閱讀排行榜

評論排行榜


    首先請大家先看下面代碼:
    typedef struct
    {
      UINT32  NumElements;
      union
      {
         UINT32  ObjectHandle;
       }Entry;
     }STR_ARRAY, *PSTR_ARRAY;

    還有這兩句#pragma pack(push, 1)
    #pragma pack(pop)
    #pragma  pack( [ n ] )

    該指令指定結構和聯合成員的緊湊對齊。而一個完整的轉換單元的結構和聯合的緊湊對齊由/ Z p 選項設置。緊湊對齊用p a c e 編譯指示在數據說明層設置。該編譯指示在其出現后的第一個結構或聯合說明處生效。該編譯指示對定義無效。當你使用#pragma  pack ( n ) 時, 這里n 為1 、2 、4 、8 或1 6 。第一個結構成員之后的每個結構成員都被存儲在更小的成員類型或n 字節界限內。如果你使用無參量的#pragma  pack , 結構成員被緊湊為以/ Z p 指定的值。該缺省/ Z p 緊湊值為/ Z p 8 。

    編譯器也支持以下增強型語法:
    #pragma  pack( [ [ { p u s h | p o p } , ] [ 標識符, ] ] [ n] )若不同的組件使用p a c k 編譯指示指定不同的緊湊對齊, 這個語法允許你把程序組件組合為一個單獨的轉換單元。帶p u s h 參量的p a c k 編譯指示的每次出現將當前的緊湊對齊存儲到一個內部編譯器堆棧中。編譯指示的參量表從左到右讀取。如果你使用p u s h , 則當前緊湊值被存儲起來; 如果你給出一個n 的值, 該值將成為新的緊湊值。若你指定一個
標識符, 即你選定一個名稱, 則該標識符將和這個新的的緊湊值聯系起來。帶一個p o p 參量的p a c k 編譯指示的每次出現都會檢索內部編譯器堆棧頂的值,并且使該值為新的緊湊對齊值。如果你使用p o p 參量且內部編譯器堆棧是空的,則緊湊值為命令行給定的值, 并且將產生一個警告信息。若你使用p o p 且指定一
個n 的值, 該值將成為新的緊湊值。若你使用p o p 且指定一個標識符,  所有存儲在堆棧中的值將從棧中刪除, 直到找到一個匹配的標識符, 這個與標識符相關的緊湊值也從棧中移出, 并且這個僅在標識符入棧之前存在的緊湊值成為新的緊湊值。如果未找到匹配的標識符, 將使用命令行設置的緊湊值, 并且將產生一個一級警告。缺省緊湊對齊為8 。p a c k 編譯指示的新的增強功能讓你編寫頭文件, 確保在遇到該頭文件的前后的緊湊值是一樣的。

    什么是內存對齊

    考慮下面的結構:

         struct foo
         {
           char c1;
           short s;
           char c2;
           int i;
          };
   
    假設這個結構的成員在內存中是緊湊排列的,假設c1的地址是0,那么s的地址就應該是1,c2的地址就是3,i的地址就是4。也就是
    c1 00000000, s 00000001, c2 00000003, i 00000004。

    可是,我們在Visual c/c++ 6中寫一個簡單的程序:

         struct foo a;
    printf("c1 %p, s %p, c2 %p, i %p\n",
        (unsigned int)(void*)&a.c1 - (unsigned int)(void*)&a,
        (unsigned int)(void*)&a.s - (unsigned int)(void*)&a,
        (unsigned int)(void*)&a.c2 - (unsigned int)(void*)&a,
        (unsigned int)(void*)&a.i - (unsigned int)(void*)&a);
    運行,輸出:
         c1 00000000, s 00000002, c2 00000004, i 00000008。

    為什么會這樣?這就是內存對齊而導致的問題。

為什么會有內存對齊

    以下內容節選自《Intel Architecture 32 Manual》。
    字,雙字,和四字在自然邊界上不需要在內存中對齊。(對字,雙字,和四字來說,自然邊界分別是偶數地址,可以被4整除的地址,和可以被8整除的地址。)
    無論如何,為了提高程序的性能,數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;然而,對齊的內存訪問僅需要一次訪問。
    一個字或雙字操作數跨越了4字節邊界,或者一個四字操作數跨越了8字節邊界,被認為是未對齊的,從而需要兩次總線周期來訪問內存。一個字起始地址是奇數但卻沒有跨越字邊界被認為是對齊的,能夠在一個總線周期中被訪問。
    某些操作雙四字的指令需要內存操作數在自然邊界上對齊。如果操作數沒有對齊,這些指令將會產生一個通用保護異常(#GP)。雙四字的自然邊界是能夠被16 整除的地址。其他的操作雙四字的指令允許未對齊的訪問(不會產生通用保護異常),然而,需要額外的內存總線周期來訪問內存中未對齊的數據。

編譯器對內存對齊的處理

    缺省情況下,c/c++編譯器默認將結構、棧中的成員數據進行內存對齊。因此,上面的程序輸出就變成了:
c1 00000000, s 00000002, c2 00000004, i 00000008。
編譯器將未對齊的成員向后移,將每一個都成員對齊到自然邊界上,從而也導致了整個結構的尺寸變大。盡管會犧牲一點空間(成員之間有空洞),但提高了性能。
也正是這個原因,我們不可以斷言sizeof(foo) == 8。在這個例子中,sizeof(foo) == 12。

如何避免內存對齊的影響

    那么,能不能既達到提高性能的目的,又能節約一點空間呢?有一點小技巧可以使用。比如我們可以將上面的結構改成:

    struct bar
    {
        char c1;
        char c2;
        short s;
        int i;
    };
    這樣一來,每個成員都對齊在其自然邊界上,從而避免了編譯器自動對齊。在這個例子中,sizeof(bar) == 8。

    這個技巧有一個重要的作用,尤其是這個結構作為API的一部分提供給第三方開發使用的時候。第三方開發者可能將編譯器的默認對齊選項改變,從而造成這個結構在你的發行的DLL中使用某種對齊方式,而在第三方開發者哪里卻使用另外一種對齊方式。這將會導致重大問題。
    比如,foo結構,我們的DLL使用默認對齊選項,對齊為
c1 00000000, s 00000002, c2 00000004, i 00000008,同時sizeof(foo) == 12。
而第三方將對齊選項關閉,導致
    c1 00000000, s 00000001, c2 00000003, i 00000004,同時sizeof(foo) == 8。

如何使用c/c++中的對齊選項

    vc6中的編譯選項有 /Zp[1|2|4|8|16] ,/Zp1表示以1字節邊界對齊,相應的,/Zpn表示以n字節邊界對齊。n字節邊界對齊的意思是說,一個成員的地址必須安排在成員的尺寸的整數倍地址上或者是n的整數倍地址上,取它們中的最小值。也就是:
    min ( sizeof ( member ),  n)
    實際上,1字節邊界對齊也就表示了結構成員之間沒有空洞。
    /Zpn選項是應用于整個工程的,影響所有的參與編譯的結構。
    要使用這個選項,可以在vc6中打開工程屬性頁,c/c++頁,選擇Code Generation分類,在Struct member alignment可以選擇。

    要專門針對某些結構定義使用對齊選項,可以使用#pragma pack編譯指令。指令語法如下:
#pragma pack( [ show ] | [ push | pop ] [, identifier ] , n  )
    意義和/Zpn選項相同。比如:

    #pragma pack(1)
    struct foo_pack
    {
        char c1;
        short s;
        char c2;
        int i;
    };
    #pragma pack()

    棧內存對齊

    我們可以觀察到,在vc6中棧的對齊方式不受結構成員對齊選項的影響。(本來就是兩碼事)。它總是保持對齊,而且對齊在4字節邊界上。

    驗證代碼

    #include <stdio.h>

    struct foo
    {
        char c1;
        short s;
        char c2;
        int i;
    };

    struct bar
    {
        char c1;
        char c2;
        short s;
        int i;
    };

    #pragma pack(1)
    struct foo_pack
    {
        char c1;
        short s;
        char c2;
        int i;
    };
    #pragma pack()


    int main(int argc, char* argv[])
    {
        char c1;
        short s;
        char c2;
        int i;

    struct foo a;
    struct bar b;
    struct foo_pack p;

    printf("stack c1 %p, s %p, c2 %p, i %p\n",
        (unsigned int)(void*)&c1 - (unsigned int)(void*)&i,
        (unsigned int)(void*)&s - (unsigned int)(void*)&i,
        (unsigned int)(void*)&c2 - (unsigned int)(void*)&i,
        (unsigned int)(void*)&i - (unsigned int)(void*)&i);

    printf("struct foo c1 %p, s %p, c2 %p, i %p\n",
        (unsigned int)(void*)&a.c1 - (unsigned int)(void*)&a,
        (unsigned int)(void*)&a.s - (unsigned int)(void*)&a,
        (unsigned int)(void*)&a.c2 - (unsigned int)(void*)&a,
        (unsigned int)(void*)&a.i - (unsigned int)(void*)&a);

    printf("struct bar c1 %p, c2 %p, s %p, i %p\n",
        (unsigned int)(void*)&b.c1 - (unsigned int)(void*)&b,
        (unsigned int)(void*)&b.c2 - (unsigned int)(void*)&b,
        (unsigned int)(void*)&b.s - (unsigned int)(void*)&b,
        (unsigned int)(void*)&b.i - (unsigned int)(void*)&b);

    printf("struct foo_pack c1 %p, s %p, c2 %p, i %p\n",
        (unsigned int)(void*)&p.c1 - (unsigned int)(void*)&p,
        (unsigned int)(void*)&p.s - (unsigned int)(void*)&p,
        (unsigned int)(void*)&p.c2 - (unsigned int)(void*)&p,
        (unsigned int)(void*)&p.i - (unsigned int)(void*)&p);

    printf("sizeof foo is %d\n", sizeof(foo));
    printf("sizeof bar is %d\n", sizeof(bar));
    printf("sizeof foo_pack is %d\n", sizeof(foo_pack));
   
    return 0;


    }




posted on 2007-12-23 20:03 sdfasdf 閱讀(17424) 評論(1)  編輯 收藏 引用 所屬分類: C++

Feedback

# re: 關于pragma pack的用法(四) C++中的內存對齊問題 2008-01-03 20:01 guojianlee
不同編譯器的,的內存對齊的參數選項不同,要注意。上次因為這個問題。搞了半死  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            在线精品国精品国产尤物884a| 欧美一二区视频| 久久精品视频在线观看| 亚洲国产精品久久久久婷婷884| 亚洲综合日韩在线| 91久久精品国产91久久性色tv| 久久久99国产精品免费| 日韩一级大片| 亚洲久久一区二区| 99热这里只有精品8| 中文一区在线| 亚洲欧美日韩中文播放| 国产一区二区三区在线播放免费观看| 欧美另类一区| 国产亚洲毛片| 亚洲精品午夜| 欧美一级视频| 亚洲高清精品中出| 午夜精品久久久久久久男人的天堂| 亚洲在线国产日韩欧美| 麻豆国产精品va在线观看不卡 | 91久久线看在观草草青青| 亚洲人成人一区二区三区| 亚洲午夜久久久久久尤物| 久久激情五月激情| 久久频这里精品99香蕉| 99精品热视频只有精品10| 亚洲一区影音先锋| 国产精品视频久久| 亚洲国产日韩欧美| 欧美在线免费视频| 一区二区三区四区精品| 午夜精品福利视频| 久久久一区二区| 午夜免费电影一区在线观看| 欧美精品九九| 亚洲精品一区二区三区在线观看 | 欧美激情综合五月色丁香小说| 欧美视频亚洲视频| 一区二区三区免费观看| 亚洲激情一区二区三区| 毛片一区二区三区| 日韩亚洲一区在线播放| 亚洲黄色成人网| 午夜亚洲精品| 欧美国产日韩一区二区在线观看 | 亚洲国产一区二区精品专区| 久久九九久久九九| 久久男女视频| 在线免费观看日本欧美| 欧美激情欧美激情在线五月| 另类av一区二区| 在线综合亚洲欧美在线视频| 亚洲国产片色| 国产欧美一区二区精品婷婷| 欧美在线一区二区三区| 久久久久久亚洲精品中文字幕| 午夜精品理论片| 国产亚洲激情| 亚洲精品在线一区二区| 国产精品swag| 欧美激情一二三区| 国产精品日韩欧美一区| 亚洲欧美国内爽妇网| 亚洲欧洲免费视频| 国产精品一区二区在线| 欧美国产国产综合| 狠狠干综合网| 欧美一区二区视频观看视频| 亚洲精品欧美精品| 久久久女女女女999久久| 午夜宅男欧美| 国产精品久在线观看| 亚洲国产精品一区二区尤物区| 国产一区二区三区在线观看网站 | 一区二区三区在线视频观看| 亚洲黄色在线看| 亚洲韩国青草视频| 麻豆av一区二区三区久久| 9i看片成人免费高清| 美玉足脚交一区二区三区图片| 99re6热在线精品视频播放速度| 欧美11—12娇小xxxx| 国产日韩久久| 久久久91精品国产一区二区精品| 欧美一级艳片视频免费观看| 欧美视频手机在线| 一区二区三区精密机械公司 | 亚洲国产三级| 欧美日韩国产麻豆| 亚洲无限av看| 蜜桃伊人久久| 中文无字幕一区二区三区| 国产精品久久久久久久久婷婷| 亚洲一级片在线观看| 免费成人黄色av| 一区二区三区视频免费在线观看| 欧美日韩亚洲一区二区三区在线 | 亚洲性感美女99在线| 欧美另类久久久品| 久久精品成人| 99re66热这里只有精品3直播 | 亚洲人午夜精品免费| 午夜在线电影亚洲一区| 亚洲激情影视| 亚洲国产精品精华液2区45| 国产精品成人在线观看| 蜜桃av一区二区三区| 久久精品视频在线观看| 性欧美video另类hd性玩具| 9l国产精品久久久久麻豆| 欧美高清视频在线| 欧美在线视频播放| 午夜欧美不卡精品aaaaa| 亚洲一区在线观看免费观看电影高清| 国内精品久久久久久| 国产午夜亚洲精品羞羞网站| 国产精品av久久久久久麻豆网| 欧美激情一区二区三区在线| 欧美91视频| 久久久夜夜夜| 美女啪啪无遮挡免费久久网站| 亚洲一区二区三区精品在线| 国产亚洲欧美色| 欧美日韩国产区| 国产精品久久久久久久久久久久久久 | 国产欧美日韩亚洲精品| 国产精品人人做人人爽| 国产日韩精品一区二区三区在线 | 欧美在线www| 久久精品国产成人| 麻豆成人在线| 亚洲美女网站| 久久精品国产第一区二区三区最新章节| 亚洲一区二区视频在线| 久久久久成人精品| 国产精品国产自产拍高清av| 国产视频在线观看一区| 国产精品成人观看视频免费| 欧美午夜一区二区福利视频| 一区二区三区在线视频播放| 亚洲一区二区三区免费在线观看| 亚洲社区在线观看| 欧美成人国产va精品日本一级| 亚洲肉体裸体xxxx137| 久久精品视频在线| 国产精品国产三级国产aⅴ浪潮 | 欧美与欧洲交xxxx免费观看 | 国产日韩精品一区二区浪潮av| 一区二区三区在线观看欧美 | 国产欧美日韩不卡| 亚洲精品精选| 亚洲高清不卡av| 久久午夜激情| 在线精品视频在线观看高清| 久久婷婷蜜乳一本欲蜜臀| 性久久久久久久久久久久| 伊人成人在线视频| 在线免费精品视频| 欧美专区在线播放| 欧美一区亚洲一区| 国产亚洲欧美aaaa| 欧美成人午夜免费视在线看片 | 亚洲第一天堂av| 欧美国产视频日韩| 亚洲一区二区三区午夜| 中文精品视频一区二区在线观看| 国产精品成人免费精品自在线观看| 亚洲精品你懂的| 亚洲一区二区动漫| 一区二区亚洲精品国产| 欧美国产欧美亚州国产日韩mv天天看完整| 久久久久久久久久久久久9999| 亚洲高清在线精品| 亚洲午夜视频| 亚洲三级视频| 先锋亚洲精品| 中日韩高清电影网| 久久久久国色av免费看影院 | 久久久久国产一区二区| 欧美激情网友自拍| 美国三级日本三级久久99| 欧美日韩在线播放三区四区| 国户精品久久久久久久久久久不卡| 久久精品国产免费看久久精品| 老**午夜毛片一区二区三区| 蜜臀av国产精品久久久久| 亚洲永久免费视频| 欧美精品粉嫩高潮一区二区| 久久久青草青青国产亚洲免观| 欧美日本不卡| 日韩系列在线| 亚洲视频在线观看三级| 欧美韩国在线| 亚洲黄色成人| 亚洲综合精品| 国内精品福利| 麻豆91精品91久久久的内涵| 乱码第一页成人| 亚洲美女电影在线|