結構體、聯合體的成員內存對齊的情況

作者:良知猶存

轉載授權以及圍觀->歡迎添加WxId:Allen-Iverson-me-LYN

 

    最近項目進行中,遇到一個小問題,在數據協議傳輸過程中,我爲了方便解析,就定義了一個結構體,在數據的指針傳入函數的時候,我用定義好的結構體進行強制轉化,沒想到一直解析失敗,調試很久,終於反應過來,在用結構體指針對數據強制轉換時,定義結構體我沒有注意到數據對齊,因爲在底層實現中,我傳入的數據buffer是排列整齊的,而強制轉化的結構體格式中,我定義的時候沒有使用__attribute__((__packed__))或者__packed強制數據對齊,導致結構體成員真實排列會按照成員中最大的變量的格式進行對其,缺少的地方被虛擬補充位置。

 

下面就稍微簡單描述一下結構體數據對齊的講解:

 圖片描述的兩種實現結構對齊的聲明,適用於結構體和聯合的聲明。

 

接下來展示幾組聲明結構體後成員變量對齊的方式:

/*第一個示例*/struct stc{    char one;    short two;    char three;    int four;} c,d;int main (void){    c.one=1;    return 0;}

    第一個示例代碼配合下方內存排列的圖片,可以看到,在正常無特殊聲明的情況下,結構體在內存排列是按照結構體成員中最大的變量的大小進行排列的。

    第一處示例代碼中,最大的成員變量是int型,一個int型在我使用的32位ARM環境中佔4個byte,所以在排列中,最小的排列單位是4byte,而其他類型,char佔1個byte,short佔2個byte,在排列的第一行的4個byte中,一個char+一個short類型爲3byte,所以需要補上1byte的虛擬空間,第二行的4byte中,還剩下一個char和int,int單獨佔一行,所以char需要補上3byte才能排列整齊。

/*第二個示例*/struct __attribute__((packed)) stc{    char one;    short two;    char three;    int four;} c,d;int main (void){    c.one=1;    return 0;}

 

 第二個示例代碼配合下方內存排列的圖片,可以看到,代碼使用了__attribute__((packed))聲明,這個聲明的含義是,令相關的結構體與聯合體強制一字節對齊。所以在內存中排列中,按照1byte的數據對齊方式,成員變量緊密排布。

/*第三個示例*/#pragma pack (2)struct stc{    char one;    short two;    char three;    int four;} c,d;int main (void){    c.one=1;    return 0;}
/*第四個示例*/#pragma pack (4)struct stc{    char one;    short two;    char three;    int four;} c,d;int main (void){    c.one=1;    return 0;}

     第三、四個示例代碼配合下方內存排列的圖片,可以看到,代碼使用了#pragma pack (n)聲明,這個聲明的含義是,令相關的結構體與聯合體強制N字節對齊,這個聲明和__attribute__((packed))功能類似,但是__attribute__((packed))只能進行一字節強制對齊,而#pragma pack (n)對齊字節數,由n進行控制,所以有很多的靈活性。具體使用可以從下圖成員對齊情況瞭解,此處就不進行贅述了。

                                                                   ————————END————————

                                                               如果大家覺得有用,可以關注我,有更多的文章。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章