記憶體對齊 --12.12 學習筆記
我們知道記憶體的最小單元是一個位元組,當cpu從記憶體中讀取資料的時候,是一個一個位元組讀取,所以記憶體對我們應該是入下圖這樣:
但是實際上cpu將記憶體當成多個塊,每次從記憶體中讀取一個塊,這個塊的大小可能是2、4、8、16等,
那麼下面,我們來分析下非記憶體對齊和記憶體對齊的優缺點在哪?
記憶體對齊是作業系統為了提高訪問記憶體的策略。作業系統在訪問記憶體的時候,每次讀取一定長度(這個長度是作業系統預設的對齊數,或者預設對齊數的整數倍)。如果沒有對齊,為了訪問一個變數可能產生二次訪問。
至此大家應該能夠簡單明白,為什麼要簡單記憶體對齊?
|
如何記憶體對齊
- 對於標準資料型別,它的地址只要是它的長度的整數倍。
- 對於非標準資料型別,比如結構體,要遵循一下對齊原則:
1. 陣列成員對齊規則。第一個陣列成員應該放在offset為0的地方,以後每個陣列成員應該放在offset為min(當前成員的大小,#pargama pack(n)) 2. 結構體總的大小,也就是sizeof的結果,必須是min(結構體內部最大成員,#pargama pack(n))的整數倍,不足要補齊。 3. 結構體做為成員的對齊規則。如果一個結構體B裡巢狀另一個結構體A,還是以最大成員型別的大小對齊,但是結構體A的起點為A內部最大成員的整數倍的地方。(struct B裡存有struct A,A裡有char,int,double等成員,那A應該從8的整數倍開始儲存。),結構體A中的成員的對齊規則仍滿足原則1、原則2。 |
手動設定對齊模數:
顯示當前packing alignment的位元組數,以warning message的形式被顯示。
將當前指定的packing alignment陣列進行壓棧操作,這裡的棧是the internal compiler stack,同事設定當前的packing alignment為n;如果n沒有指定,則將當前的packing alignment陣列壓棧。
從internal compiler stack中刪除最頂端的reaord; 如果沒有指定n,則當前棧頂record即為新的packing alignement數值;如果指定了n,則n成為新的packing alignment值
指定packing的數值,以位元組為單位,預設數值是8,合法的數值分別是1,2,4,8,16。 |
下面是我個人的一些程式碼段 ,不懂的可以加我微信或者直接再CSDN上練習我哦
#include <stdio.h>
#include <stdlib.h>
//本機的對齊模數是8 其他電腦可能不同,輸出結果可能有誤!!
/* #pragma pack(show) 顯示當前packing alignment的位元組數,以warning message的形式被顯示*/
/* #pragma pack(push) 將當前指定的packing alignment陣列進行壓棧操作,這裡的棧是the internal
compiler stack,同事設定當前的packing alignment為n;如果n沒有指定,則將當前的packing alignment
陣列壓棧。*/
/* #pragma pack(pop) 從internal compiler stack中刪除最頂端的reaord; 如果沒有指定n,則當前棧頂
record即為新的packing alignement數值;如果指定了n,則n成為新的packing alignment值*/
typedef struct
{
int a; // 0-3
char b; // 4-7
double c; //8-15
float d; // 20
} Student ;
Student stu1 ;
#pragma pack(1) // 修改現在的記憶體模數
typedef struct
{
int a; // 0-3
char b; // 4-7
double c; //8-15
float d; // 20
} Student1 ;
Student1 stu2 ;
void text01() // 測試記憶體對齊
{
printf("%d\n",sizeof stu1); // 算出來的sizeof實際上是24 為何呢? 記憶體對齊與對齊模數
/*所以Student內部對齊之後的大小為20 ,整體對齊,整體為最大類
型的整數倍 也就是8的整數倍 為24*/
printf("%d\n",sizeof stu2);
}
#pragma pack(8)
typedef struct
{
int a; // 0-3
Student stuT;
double b ;
} Student2 ;
Student2 stu3 ;
void text02()
{
printf("%d\n",sizeof stu3);
}
int main(void)
{
//text01();
text02();
}