c語言-結構體在內存中的存放形式


第一篇博客,請大家多多包涵!

結構體在內存中的存放形式:

使用sizeof()運算符計算結構體在內存中所占用的字節數很明顯可以看到與實際聲明類型的字節數不同。(sizeof() 是用來計算類型在內存中所占字節數的大小)

對於剛入門的同學肯定會很疑惑,結構體在內存中到底是怎樣存放的呢?

  • 首先說明一個概念-字節對齊
    這個概念有很多叫法,這里我們就叫字節對齊。字節對齊就是數據類型按照固定的字節大小排列,方便計算機cpu、內存等的讀取。結構體中的數據類型並不是都相同的,這個時候就需要字節對齊來提高計算機的讀取效率。

  • 結構體會進行字節對齊,默認情況下字節對齊的單位是當前結構體體中非構造類型所占最大字節數。
    可能我描述的有點繞,簡單來說就是:你在結構體中描述了int 和 char類型,那么編譯器(本人用的是gcc編譯器,不同編譯器可能會有差異)會默認對齊單位是int所占字節數,如果加上double類型,那么默認為8字節。

  • 連續的數據類型所占字節數如果加起來不大於對齊單位,則會放在一起讀取,否則就會把位置預留出來。
    比如:結構體描述了int 和 2個連續的char類型,默認情況下,總共占用8字節;int占4字節,每個char占用2字節,剩余兩個字節空出來。但是這兩個空出來的空間屬於結構體的,其他變量無法寫入,算是廢棄空間。如果是自學的話,這一點可能會忽略,導致看不懂結構體的存儲方式,下面我會使用一些簡單的例子來驗證。

  • 通過一些預編譯手段來自定義對齊單位

pragma pack(n) 預編譯實現,自定義設置對齊單位,其中n只能是2的次方且不能超過構造體內非構造類型所占最大字節數(超過則n無效)。

struct NAME{構造描述}attribute((packed)); 如果是gcc編譯器可以使用 attribute((packed)) 指令告訴編譯器取消字節對齊,這條指令是gcc編譯器特有的。

用幾個小例子就可以發現結構體在內存中存放的規律:

  • test1
struct test1_st
{
    int i;
    char c;
};
int main()
{
    struct test1_st test1 = {};

    printf("%lu\n",sizeof(test1));
}

運行結果:

8

很明顯一個int加一個char類型占的應該是5個字節,在結構體中卻是8字節。說明存在字節對齊。

  • test2
struct test2_st
{
    int i;
    char c;
    char c2;
};
int main()
{
    struct test2_st test2 = {};

    printf("%lu\n",sizeof(test2));
}

運行結果:

8

這次我只是在結構體中多加了一個char類型,可他們占用的還是8字節。說明:連續的數據類型所占字節數如果加起來不大於對齊單位,則會放在一起讀取!我們可以把他們的順序調整一下。

  • test3
struct test3_st
{
    char c;
    int i;
    char c2;
};
int main()
{
    struct test3_st test3 = {};

    printf("%lu\n",sizeof(test3));
}

運行結果:

12

我們這次把char c 調到了頂部,char c 與 char c2 已經不是連續的了。這時查看運行結果為 12 ,證明了上述理論。

  • 小例子就這些,大家可以使用不同的類型來嘗試一下,如果發現與我論述內容有不同的地方,或者是文中的錯誤,都可以評論告之。
    還有自定義或取消對齊單位,主要是用於數據傳輸,畢竟不同平台可能存儲略有差異,萬一傳輸內容都是廢棄空間,那豈不是很尷尬!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM