一.記憶體對齊介紹
目前的計算機系統中 cpu都是按照位元組進行讀取儲存的記憶體資料,訪問某乙個變數的時候 需要在特定的位址空間中訪問,此時就需要各種不同型別的變數在記憶體空間中按照一定的規則進行排放,而不是乙個接乙個的進行有序排放。所以現代編譯器中都會對記憶體進行自動的對齊。
struct struct1
;上面的struct1 所佔的空間大小是12,char a 是 1 個位元組,int b 是4 個位元組,short c 是2 個位元組,經過記憶體對齊後大小是12(後面會說明為啥是12)
二.記憶體對齊的作用
1.平台原因
各個硬體平台對儲存空間的處理上有很大的不同。一些平台對某些特定型別的資料只能從某些特定位址開始訪問。某些架構的cpu讀取沒有對齊的記憶體資料時,可能會出錯。
2.效能原因 (可以提高訪問效率)
對於乙個32位的作業系統,假設每次讀取都是從偶位址位置開始讀取。乙個int 型變數,如果訪問在偶位址的開始位置,那麼系統可以在乙個讀週期中取出這個int 變數,如果要是存放在奇位址位置,那麼系統需要讀取兩次,對兩次讀取後的結果進行拼接才能得到這個int 型變數值。效能明顯增加。
三.記憶體是怎麼對齊的?
每個平台都是有自己的編譯器係數,通過預編譯命令#pragma pack(n)
,n=1,2,4,8,16 來改變這一係數,其中 n 就是你要指定的「對齊係數」。
對齊的規則:
(1).對齊的有效值是,取#pragma pack(n) 中n 和結構體中最長資料長度的較小的乙個。
(2).結構體struct中的成員變數在記憶體中的分配是連續的,struct內的首位址也就是第乙個資料成員的位址,亦可理解為 struct內第乙個資料成員的位址與struct首位址的偏移量offset = 0.
(3).struct內資料成員,在第乙個資料成員之後,每乙個資料成員距離struct首位址的offset的距離是有效對齊值的整數倍,如果不是整數倍,那麼在對齊的時候,會在這個成員的資料前新增空的位元組達到整數倍。(有效對齊值指的是#pragma pack(n) 中n 和結構體中資料成員最長長度進行比較,取其中的較小的乙個
)
(4). 結構體的整體對齊準則
資料成員對齊之後,還要進行整體對齊。 如果資料對齊完成時struct
的大小不是對齊有效值的整數倍。就要在struct
的最後新增空位元組直到對齊。看下面乙個簡單的例子,n = 8, struct中 int b的長度最長 是佔4個位元組,所以對齊有效值為4
struct struct1
;char a 的offset是0,a佔乙個位元組,所以需要在a 錢新增3個空位元組,000x,此時b 的offset是4,是對齊有效值的整數倍,不需要新增空位元組,***x,short c的offset是8,且c長度是2,所以一共是4+4+2 = 10,不是有效值的倍數,所以後面新增2個空位元組進行對齊,此時struct1的長度是12。
四。簡單例項
從上面 我們可以看出來,記憶體對齊的優點,在某種程度上 可以提高程式的效能。下面我們看乙個簡單的例子來說明這個問題。
執行的結果如下:#include #include #include #include#include#include using namespace std;
struct struct1 //沒有對齊
;struct struct2 //已經對齊;
void test1()
gettimeofday(&end,null);
long long int time = ( end.tv_sec - start.tv_sec ) * 1000 * 1000 + end.tv_usec - start.tv_usec;
cout << "** test1 cost time is :" << time << endl; }
void test2()
gettimeofday(&end,null);
long long int time = ( end.tv_sec - start.tv_sec ) * 1000 * 1000 + end.tv_usec - start.tv_usec;
cout << "** test2 cost time is :" << time << endl; }
int main()
struct1沒有進行記憶體對齊,struct2進行記憶體對齊,從執行結果可以看出沒有進行記憶體對齊的資料結構 計算時候 效能消耗比記憶體對齊的要大。
記憶體那些事
linux中的free m可以檢視當前的記憶體使用情況 yejianfeng iz23fsd free m total used free shared buffers cached mem 7869 7737 132 0 489 4419 buffers cache 2828 5040 swap ...
記憶體的那些事
堆 heap 為程式儲存的一塊記憶體區域,用來儲存那些在執行時才知道其存在與大小的資料 程式能夠從堆中分配記憶體給這些元素 在用完之後,應該釋放掉這些記憶體。堆中所有的的東西都是匿名的 不能按名字直接訪問只能通過指標間接的訪問 棧 stack 為程式儲存的一塊記憶體區域,用來儲存狀態資料,例如 過程...
C語言中關於記憶體那些事
c語言的程式記憶體布局,從高到低依次為 棧區 堆區 未初始化資料區 初始化資料區 區。一 棧區 由編譯器自動管理,無需程式設計師手工控制。存放函式的引數值 區域性變數的值等。棧區內容從高位址到低位址分配,從低位址到高位址訪問。int a 0 int b 0 int array 5 printf a....