windows下結構體的資料對齊

來源:互聯網
上載者:User
前言

比如有些平台每次讀都是從偶地址開始,如果一個int型(假設為32位系統)如果存放在偶地址開始的地方,那麼一個讀周期就可以讀出,而如果存放在奇地址開始的地方,就可能會需要2個讀周期,並對兩次讀出的結果的高低位元組進行拼湊才能得到該int資料。資料對齊(Data Alignment) 這個要求可以提高儲存空間系統的效能,減少定址次數,代價是浪費了一些空間。換句話說是用相對廉價的空間換得時間。

資料對齊

在我電腦上的各基本類型的所佔位元組數如下:

有結構體A如下:

   1: struct A

   2: {

   3:     int i;

   4:     double d;

   5:     char c;

   6:     short s;

   7: };

資料對齊有兩種方式,一種是自然對齊,另一種是強制對齊。

自然對齊

結構體資料自然對齊要滿足的條件:

1. 假設資料的位移量X,資料所屬類型所佔位元組數b,那麼需要滿足 X % b == 0。

2. 假設結構體中所佔總位元組數為N,結構體中占位元組數最大的資料類型(比如結構體A中的double)的位元組數為B。那麼需要滿足 N % B == 0。

現在分析結構體A

int i; int型佔4個位元組,結構體的第一個資料,所以位移量為0(位移量的單位是位元組),能夠整除4,滿足條件一

double d; double 型佔8個位元組,位移量為4,不能夠整除8,不滿足條件一,所以將其位移量後移至8,從而滿足條件一。

char c; char型佔1個位元組,位移量為16,能夠整除1,滿足條件一。

short s; short型佔2個位元組,位移量為17,不能夠整除2,不滿足條件一,所以將其位移量後移至18,從而滿足條件一。

綜上所述: i的位移量是0,d的位移量是8,c的位移量是16,s的位移量是18。

假設struct A的起始地址為Addr,那麼i,d,c,s的記憶體位址是Addr+各自的位移量。

將所有位元組加起來應該是20個位元組,即struct A所佔的記憶體空間應該是(結構體A的起始地址 ~ 結構體A的起始地址+19)。但是不滿足條件2,在struct A中占位元組數最大的資料類型是double佔8個位元組,所以總位元組數為24。如何驗證這一說呢?可以聲明一個結構體數組A a[2];如果struct A真的占位元組數為24,那麼&a[1].i – &a[0].i的值應該等於24。換言之,short s佔了兩個位元組之後還另佔了4個位元組的記憶體位址保持資料的對齊,&a[1].i – &a[0].i = 6。有圖有真相:

觀察到兩點

1.每個資料的記憶體位址都是struct A的起始地址(0x002afbac)+各自的位移量。

2.&a[1].i  - &a[0].s = 6從而驗證了上面加粗字的內容為真。

強制對齊

強制對齊需要用到#pragma pack

   1: #pragma pack(1)

   2:  

   3:     struct B

   4:     {

   5:         int i;

   6:         double d;

   7:         char c;

   8:         short s;

   9:     };

  10: #pragma pack()

先不理會#pragma pack的具體功能,只需要知道它有一個參數即可。

結構體的強制對齊要滿足:

1. 假設資料的位移量X,資料所屬類型所佔位元組數b1,#pragma pack(b2)的參數為b2,那麼需滿足 X % ( min ( b1, b2) ) == 0。

2. 假設結構體中所佔總位元組數為N,結構體中占位元組數最大的資料類型(比如結構體A中的double)的位元組數為B1,#pragma pack(b2)的參數為B2,那麼應該滿足

N % ( min( B1, B2) ) == 0。

#pragma pack( n ) 的作用就在條件1,2中體現了,也體現了強制對齊與自然對齊的區別。

現在分析結構體B(與結構體唯一的區別就是加了pack)所佔的總位元組數:

int i;位移量為0,能夠整除min (4, 1)。

double d;位移量為4,能夠整除min (8, 1)

char c;位移量為12,能夠整除min (1, 1)

short s;位移量為13,能夠整除min (2, 1)

所以最後的總位元組數為15。又15能夠整除min (8, 1),滿足條件2,因此最後的總位元組數為15。見真相:

總結

自然對齊其實是有預設的pack,在我的電腦中它的預設值為8(可通過#pragma pack(show)來查詢預設值,啟動並執行時候在警告欄中顯示),也就是本文中的自然對齊與

   1: #pragma pack(8)

   2:  

   3:     struct A

   4:     {

   5:         int i;

   6:         double d;

   7:         char c;

   8:         short s;

   9:     };

  10: #pragma pack()

是等價的。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.