C語言中結構體、聯合體的成員內存對齊情況

前言

最近項目進行中,遇到一個小問題,在數據協議傳輸過程中,我為瞭方便解析,就定義瞭一個結構體,在數據的指針傳入函數的時候,我用定義好的結構體進行強制轉化,沒想到一直解析失敗,調試很久,終於反應過來,在用結構體指針對數據強制轉換時,定義結構體我沒有註意到數據對齊,因為在底層實現中,我傳入的數據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進行控制,所以有很多的靈活性。具體使用可以從下圖成員對齊情況瞭解,此處就不進行贅述瞭。

總結

到此這篇關於C語言中結構體、聯合體的成員內存對齊情況的文章就介紹到這瞭,更多相關C語言結構體、聯合體內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: