c語言之字節對齊-初步認識

1.字節對齊的概念
(1)背景

當系統爲我們劃分一段連續內存空間時,cpu在訪問內存空間數據理論上時可以從任意地址訪問隨機大小的數據。但是由於硬件方面和操作系統的問題,
CPU在讀寫內存的時候是以內存塊來讀取內存的,所以如果在讀取了一個int數據緊接着又讀取一個char型數據,那麼可能cpu會直接讀取到更多的地址。
然後再重新定位到char的內存地址上。當然,這是在每個數據都連續內存存放的情況下,顯然,CPU的訪問效率會降低很多。
(2)什麼是字節對齊
爲了提高CPU的內存訪問效率。於是引入了字節(內存)對齊的概念,毫無疑問,字節對齊是通過消耗內存空間來換取CPU效率的一個手段。

2.字節對齊的準則
(1)基本數據類型的自身對齊值
(2)程序的指定對齊值(#pragma pack(value)時的value)
(3)自定義類型的自身對齊值(即結構體或類成員自身對齊值最大的值)
(4)自定義類型的有效對齊值(自定義類型的自身對齊值和指定對齊中較小的值)

3.字節對齊實例
(1)普通結構體對齊

struct Test1             // 對齊情況下爲24,不對齊情況下爲13,本身對齊值爲8
{
    int a;                   // 4+4            4指定對齊值爲4,自身對齊值爲8
    double b;            // 8                8
    char c;                // 1+7            1+3            
};
對於struct Test結構體,按照我們猜想,整個結構體在內存中所佔字節應該是4+8+1=13,但是我們用printf("%d\n",sizeof(struct Test));輸出24。
別忘了內存對我們的數據對齊了。由於我們沒有對程序指定對齊值,那我們先看變量a,自身對齊值4bytes,變量b佔用8bytes,這時候自身對齊值爲8。
需要在a的4字節後面再填充4個字節。c佔一個字節,後面沒有數據。這個時候Test中成員所佔內存空間就是4+4+8+1=17。
但是結構體本身需要按照最寬數據成員對齊值的整數倍對齊,所以struct Test的自身對齊值爲7填充在c之後,struct Test的實際對齊值就是17+7=24。
(2)上述順序調換
struct Test2                 // 最終大小是自定義大小的整數倍
{
    char c;                    // 1+3
    int a;                       // 4
    double b;                // 8, 這個地方要看上面整體開闢空間是8的倍數字
};
和(1)一樣只是把結構體成員的順序做調換,c這個時候4Bytes,a也是4Bytes,b佔8個bytes,整個Test結構體大小必須是8的倍數,現在就是1+3+4+8=16。
(3)更多普通結構體對齊實例
struct Test3                    // 16
{
    double a;                    // 8
    char b;                       // 4
    int c;                          // 4
};

struct Test4             // 3
{
    char a;                // 1
    char b;                // 1
    char c;                // 1
};
同理,Test3裏面a佔8個字節,b有1+3個字節,c有4個字節,結構體大小對齊8+4+4=16字節,不額外增加對齊值。而Test4中都是char類型,所以Test4大小3Bytes。
(4)我們可以發現在系統默認的存在字節對齊的概念下,讓高字節的數據類型放在結構體後面總是能消耗較少的內存空間。

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