結構體字節對齊

結構體字節對齊

什麼是對齊?爲何要對齊?

  • 現代計算機中內存空間都是按照byte劃分的,從理論上講彷佛對任何類型的變量的訪問能夠從任何地址開始,但實際狀況是在訪問特定變量的時候常常在特定的內存地址訪問,這就須要各種型數據按照必定的規則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。
  • 若是不按照適合其平臺要求對數據存放進行對齊,會在存取效率上帶來損失。好比有些平臺每次讀都是從偶地址開始,若是一個int型(假設爲32位系統)若是存放在偶地址開始的地方,那麼一個讀週期就能夠讀出,而若是存放在奇地址開始的地方,就可能會須要2個讀週期,並對兩次讀出的結果的高低字節進行拼湊才能獲得該int數據。顯然在讀取效率上降低不少。

#pragma pack()語法

  • #pragma pack 的主要做用就是改變編譯器的內存對齊方式,這個指令在網絡報文的處理中有着重要的做用,#pragma pack(n)是他最基本的用法,其做用是改變編譯器的對齊方式, 不使用這條指令的狀況下,編譯器默認採起#pragma pack(8)也就是8字節的默認對齊方式,n值能夠取(1, 2, 4, 8, 16) 中任意一值。
  • 咱們常說編譯器默認8字節對齊咱們怎麼知道的呢?#pragma pack(show)顯示當前內存對齊的字節數。顯示當前packing aligment的字節數,以warning message的形式顯示。

image.png

結構體對齊的規則

原則1:數據成員對齊規則:結構(struct)(或聯合(union))的數據成員,第一個數據成員放在offset爲0的地方,之後每一個數據成員的對齊按照#pragma pack指定的數值和這個數據成員自身長度中,比較小的那個進行。(即pack指定的值和成員自身比較,小的那個整數倍對齊)markdown

原則2:結構(或聯合)的總體對齊規則:在數據成員完成各自對齊以後,結構(或聯合)自己也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大數據成員長度中,比較小的那個進行。(即pack指定的值和最大成員自身比較,小的那個整數倍對齊)網絡

原則3:結構體做爲成員:若是一個結構裏有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲。數據結構

結構體對齊驗證

#pragma pack(2)
struct Struct1{
    double a; //0-7
    char b;   //8
    int c;    //起始min(2,4)=2,因此從2的倍數開始 10 11 12 13
    short d;  //14 15
} structOne;  //min(2,8)=2, 2的倍數 16
#pragma pack()

struct Struct2{
    double a; //0-7
    char b;   //8
    int c;    //起始min(8,4)=4,因此從4的倍數開始 12 13 14 15
    short d;  //16 17
} structTwo;  //min(8,8)=8, 8的倍數 24 
複製代碼

運行結果:大數據

image.png 能夠看出此時structOne和structTwo,內部成員變量順序徹底一致,指定了#pragma pack()以後sizeof獲得的結果徹底不一樣。spa

  • 那麼若是編譯器默認8字節對齊時,成員相同順序不一樣,結構體的字節又是多少呢?
#pragma pack(show)
struct Struct1{
    double a; //0-7
    char b;   //8
    int c;    //起始min(8,4)=4,因此從4的倍數開始 12 13 14 15
    short d;  //16 17
} structOne;  //min(8,8)=8, 8的倍數 24; 

struct Struct2{
    double a; //0-7
    int c;    //起始min(8,4)=4,因此從4的倍數開始 8 9 10 11
    char b;   //12
    short d;  //14 15
} structTwo;  //min(8,8)=8, 8的倍數 16
複製代碼

運行結果code

image.png 能夠看出結構體成員順序不一樣,雖然pragma pack相同,sizeof獲得的字節數不一樣。orm

  • 若是將structOne中的double a拆解成兩個int成員,structOne的字節數應是20了

image.png

這是由於結構體總體對齊,是按照最大成員變量int長度的和pack默認的8中最小比較是4,4的最小倍數是20;內存

  • 結構體嵌套

image.png

image.png

  • 對比兩張圖明顯發現,當出現結構體嵌套時,外層結構體總體對齊時,取得是內外結構體中最大成員變量的倍數

總結

結構體的對齊顯示成員對齊,而後是結構體的總體對齊,根據內存對齊原則,來對齊內存。編譯器

1:根據數據成員對齊:it

根據#pragma pack(x) 根據x這個數值和依次排列的數據成員自身的長度的數作比較,那個小用哪一個。

這樣就排出來了每個數據所佔的地址及位置。是依次排列,可是不是依次挨着排列,要排列的數據要看本身數據成員自身長度的數和x哪一個更小,假設自身數據長度爲4,x爲8,則再看本身要依次排列的地址是否是4的倍數,若是不是,則自動延長地址到4的倍數處,再賦值。

2:數據結構對齊:

當上面那個對齊了每個數據成員後, 如今須要對數據結構總體長度對齊。找出數據結構成員中最大長度的數據的值z,跟x作對比,找到最小的那個,假設x爲8,z爲4,則總體數據結構長度應該是4的整數倍,不夠自動補齊。

3:結構體做爲成員

若是成員內有結構體,須要看結構體中最大的成員的長度h來作比較,是h的倍數。

相關文章
相關標籤/搜索