內存對齊的原則

1.結構體的第一個元素地址必須是0x…..0(是受內存對齊這個影響產生的結果)
2.結構體成員地址是通過對齊規則和自身大小共同影響的,規則如下:
如果設定對齊方式爲n個字節對齊,而某結構體成員大小爲m,那麼該結構體成員的地址必須爲min(n,m)的整數倍,比如double在64位平臺是8字節,指定對齊方式爲1個字節對齊,則地址隨意,若爲2個字節對齊,則地址只能是0 2 4 8
3.通過以上方式,即可算出結構體所有成員(附帶填充所佔字節)的大小q,而結構體的大小必須爲大於q的min(n,maximum)的最小整數倍(n語義同上,maxiumum爲最大的成員字節數)

下面我們來通過實例來搞懂上面的規則

#include <iostream>

using std::cout;
using std::endl;
#pragma pack(1)
struct Test {
    char c;     // 1 byte
    double d;   // 8 byte
    int i;      // 4 byte
    short s;    // 2 byte
    float f;    // 4 byte
};
#pragma pack()

#pragma pack(2)
struct Test2 {
    char c;     // 1 byte
    double d;   // 8 byte
    int i;      // 4 byte
    short s;    // 2 byte
    float f;    // 4 byte
};
#pragma pack()

#pragma pack(8)
struct Test8 {
    char c;     // 1 byte
    double d;   // 8 byte
    int i;      // 4 byte
    short s;    // 2 byte
    float f;    // 4 byte
};
#pragma pack()
int main() {
    //Test結構體以1字節對齊,總大小爲1的倍數 因此爲所有成員大小之和即可無需填充
    Test test;

    printf("Test 以%ld byte 對齊\n",alignof(Test));
    printf("Test結構體大小: %ld\n",sizeof(Test));
    printf("Test.c address:  %p\n",&test.c);
    printf("Test.d address:  %p\n",&test.d);
    printf("Test.i address:  %p\n",&test.i);
    printf("Test.s address:  %p\n",&test.s);
    printf("Test.f address:  %p\n",&test.f);
    //Test結構體以2字節對齊,總大小必須爲2的倍數,成員與成員填充之和爲(可以通過地址相減加尾元素大小) 20爲2的倍數無需填充
    Test2 test2;    
    printf("Test2 以%ld byte 對齊\n",alignof(Test2));
    printf("Test2結構體大小: %ld\n",sizeof(Test2));
    printf("Test2.c address:  %p\n",&test2.c);
    printf("Test2.d address:  %p\n",&test2.d);
    printf("Test2.i address:  %p\n",&test2.i);
    printf("Test2.s address:  %p\n",&test2.s);
    printf("Test2.f address:  %p\n",&test2.f);
    //Test結構體以8字節對齊,總大小必須爲8的倍數,成員與成員填充之和爲 27不爲8的倍數,繼續填充直到32
    Test8 test8;    
    printf("Test8 以%ld byte 對齊\n",alignof(Test8));
    printf("Test8結構體大小: %ld\n",sizeof(Test8));
    printf("Test8.c address:  %p\n",&test8.c);
    printf("Test8.d address:  %p\n",&test8.d);
    printf("Test8.i address:  %p\n",&test8.i);
    printf("Test8.s address:  %p\n",&test8.s);
    printf("Test8.f address:  %p\n",&test8.f);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章