1. 程式人生 > >結構體記憶體對齊總結

結構體記憶體對齊總結

  首先我們都知道結構體是多個變數的集合,在其中可以存放整型,浮點型等等各種,然後結構體記憶體是如何對齊的呢,他並不是按連續順序去排下去的,首先我們先上一段程式碼

#include<iostream>
#include<cstdlib>
using namespace std;

struct a{
	int m;
	char n;
	double c;

};

struct b{
	char o;
	double p;
	int j;
};

int main()
{
	cout << sizeof(a) << endl;
	cout << sizeof(b) << endl;
	system("pause");
}

這段程式碼執行出來的結果得出a的記憶體大小為16,b的記憶體大小為24,同樣的三個型別,只是排列順序不同,結構體的大小就不一樣。下面是對齊規則

結構體記憶體對齊規則
1. 第一個成員在與結構體偏移量為0的地址處。
2. 其他成員變數要對齊到某個數字(對齊數)的整數倍的地址處。
對齊數 = 編譯器預設的一個對齊數 與 該成員大小相比中的較小值。
VS中預設的對齊數為8,gcc中的對齊數為4
3. 結構體總大小為:最大對齊數(所有變數型別最大者與預設對齊引數取最小)的整數倍。
4. 如果嵌套了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是
所有最大對齊數(含巢狀結構體的對齊數)的整數倍。

 

那麼為什麼要記憶體對齊呢

記憶體對齊大大提高了cpu的讀取速率。

1.還有並非所有硬體平臺都可以訪問任何地址上的任何資料,有些硬體平臺也只能訪問某些特定地址處某些特定型別的資料。

2.記憶體對齊的CPU只需要讀取一次,沒有記憶體對齊,CPU則需要讀取兩次。

如何讓結構體按照指定的對齊引數進行對齊

設定對齊引數可在結構體struct之前加上#pragma pack(對齊數),在struct之後加上#pragma pack;便可以設定對齊引數

 如何知道結構體中某個成員相對於結構體起始位置的偏移量

我們可以使用這個#define offsetof(s,a)  (size_t)  (((s*)0)->a),這個用法就是我們告訴編譯器有一個指標指向結構體s,而它的值是0,然後我們取結構體中的a,a的地址就是a的偏移量了。

#include<iostream>
#include<cstdlib>
using namespace std;
#define offsetof(s,a) (size_t) &(((s*)0)->a)

struct a{
	int m;
	char n;
	double c;

};
#pragma pack(4)
struct b{
	char o;
	double p;
	int j;
};
#pragma pack;
int main()
{
	cout <<"a的記憶體大小為"<< sizeof(a) << endl;
	cout <<"b的記憶體大小為"<< sizeof(b) << endl;
	cout << offsetof(b, p) << endl;
	system("pause");
}