C/C++—— 記憶體位元組對齊規則

readyao發表於2016-04-01

記憶體對齊規則:

1.資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第一個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小或者成員的子成員大小(只要該成員有子成員,比如說是陣列,結構體等)的整數倍開始(比如int在32位機為4位元組,則要從4的整數倍地址開始儲存。

比如:

struct s1{
        char a;
        short b;
        double c;
};

該結構體的大小為16個位元組。首先a佔有1個位元組,a從偏移量為0處開始存放。b為short型別,大小為2,所以b從偏移量為2處開始存放。那麼偏移量為1處沒有存放資料。c大小為8個位元組,所以c從偏移量為8處開始存放。所以該結構體佔有16個位元組。如果c大小為4個位元組,所以c從偏移量為4處開始存放。所以該結構體佔有8個位元組。

2.結構體作為成員:如果一個結構裡有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始儲存.(struct s2裡存有struct s1,s1裡有char,int ,double等元素,那s1應該從8的整數倍開始儲存.)

struct s1{
        char a;
        short b;
        double c;
};

struct s2{
        char d;
        struct s1 s11;
};

結構體s1佔用16個位元組空間。s1中最大元素的大小為8個位元組,所有該結構體應該從8個整數倍地址開始儲存,前面只有一個位元組的d變數。所有s1結構體應該從偏移量為8處開始存放。所以該結構體佔有8+16=24個位元組。

3.結構體的總大小,也就是sizeof的結果,必須是其內部最大成員的整數倍.不足的要補齊.

struct s3{
        char a;
        double b;
        short c;    
};

結構體s3佔用24個位元組空間。a從偏移量為0處開始存放。b從偏移量為8處開始存放。c從偏移量為16處開始存放(佔用兩個位元組)。貌似是18個位元組啊,但是要滿足規則3,結構體的大小必須是內部最大成員的整數倍,也就是應該是8個整數倍,最小隻能是24。

例項原始碼:

#include <iostream>
using namespace std;
//#pragma pack(4)
//大小為16個位元組,參考第一個規則
struct s1{
    char a;
    short b;
    double c;
};

//大小為24個位元組,參考第二個規則
struct s2{
    char d;
    struct s1 s11;
};

//大小為24個位元組,參考第三個規則
struct s3{
    char a;
    double b;
    short c;
};


int main()
{
    cout << "sizeof(s1) = " << sizeof(struct s1) << endl;
    cout << "sizeof(s2) = " << sizeof(struct s2) << endl;
    cout << "sizeof(s3) = " << sizeof(struct s3) << endl;

    return 0;
}

輸出為:
sizeof(s1) = 16
sizeof(s2) = 24
sizeof(s3) = 24

#pragma pack(n)簡單介紹:

編譯器中提供了#pragma pack(n)來設定變數以n位元組對齊方式。
n位元組對齊就是說變數存放的起始地址的偏移量有兩種情況:
第一、如果n大於等於該變數所佔用的位元組數,那麼偏移量必須滿足預設的對齊方式。預設對齊方式就是上面的三個規則。
第二、如果n小於該變數的型別所佔用的位元組數,那麼偏移量為n的倍數,不用滿足預設的對齊方式。

結構的總大小也有個約束條件,分下面兩種情況:
如果n大於所有成員變數型別所佔用的位元組數,那麼結構的總大小必須為佔用空間最大的變數佔用的空間數的倍數;否則必須為n的倍數。

比如上面的例子我按 #pragma pack(4),以4位元組對齊的方式得到下面的結果。

struct s1{
        char a;
        short b;
        double c;
};

佔有2+2+8 = 12位元組。總大小必須是4的整數倍。

struct s2{
        char d;
        struct s1 s11;
};

佔有4+12 = 16位元組。

struct s3{
        char a;
        double b;
        short c;    
};

佔有4+8+4 = 16位元組。

例項原始碼:

#include <iostream>
using namespace std;
#pragma pack(4)
//大小為16個位元組,參考第一個規則
struct s1{
    char a;
    short b;
    double c;
};

//大小為24個位元組,參考第二個規則
struct s2{
    char d;
    struct s1 s11;
};

//大小為24個位元組,參考第三個規則
struct s3{
    char a;
    double b;
    short c;
};


int main()
{
    cout << "sizeof(s1) = " << sizeof(struct s1) << endl;
    cout << "sizeof(s2) = " << sizeof(struct s2) << endl;
    cout << "sizeof(s3) = " << sizeof(struct s3) << endl;

    return 0;
}

輸出:
sizeof(s1) = 12
sizeof(s2) = 16
sizeof(s3) = 16

相關文章