**:
當我們聽到」記憶體對齊「這個概念時,從字面意思來看,很容易理解。那就是讓記憶體按一定規則對齊。
當然 就會有人說 你這不是廢話 ??
現在我就來說一說為什麼要記憶體對齊以及怎麼個對齊法(如何對齊)?
記憶體對齊:
記憶體對齊」應該是
編譯器的「管轄範圍」。編譯器為程式中的每個「
資料單元
對於記憶體對齊問題,主要存在於struct和union等復合結構在記憶體中的分布情況,許多實際的計算機系統對基本型別資料在記憶體中存放的位置有限制,它們要求這些資料的首位址的值是某個數m(通常是4或8);對於記憶體對齊,主要是為了提高程式的效能,資料結構,特別是棧,應盡可能在自然邊界上對齊,經過對齊後,cpu的記憶體訪問速度大大提公升。
windows中預設對齊數為8,linux中預設對齊數為4;
(1)記憶體對齊的主要作用
:1、平台原因(移植原因)
a 不是所有的硬體平台都能訪問任意位址上的任意資料的;
b 某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。
2、效能原因:
a 資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。
b 原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。
(2)記憶體對齊規則:
在記憶體中,編譯器按照成員列表順序分別為每個結構體變數成員分配記憶體,當儲存過程中需要滿足邊界對齊的 要求時,編譯器會在成員之間留下額外的記憶體空間。
如果想確認結構體占多少儲存空間,則使用關鍵字sizeof,如果想得知結構體的某個特定成員在結構體的位置,則使用offsetof巨集(定義於stddef.h)。
1、資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,
第乙個資料成員放在offset為0的地方
,以後每個資料成員的對齊
按照#pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。
2、結構(或聯合)的整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將
按照#pragma pack指定的數值和結構(或聯合)最大資料成員長度中,比較小的那個進行。
3、結合1、2可推斷:當#pragma pack的n值等於或超過所有
資料成員
長度的時候,這個n值的大小將不產生任何效果。
我們來看一下下面的例子:
#include#includeusing namespace std;
#pragma pack(4)
struct m
;int main()
上面**執行結果:
從執行結果來看我們可以證實上面記憶體對齊規則的第一條:第乙個資料成員放在offset為0的地方;
現在咱來看看上面結構體是如何記憶體對齊的;先用**列印它們每個資料成員的儲存位址的偏移量:
int main()
看看結果:
在此c在結構體中偏移量為8加上它自身(int)4個位元組,剛好是12(c的開始位置為8,所以要加它的4個位元組)
現在我來給大家分析一下:
上面記憶體結束為11,因為0-11,12是最大對齊數的整數倍,故取其臨近的倍數,所以就取4的整數倍即12;
上圖中我用連續的陣列來模仿記憶體,如圖是它們的記憶體對齊圖;
如果將最大記憶體對齊數改為8,他將驗證記憶體對齊規則中的第3條。
如果將其改為2,會發生什麼:我們來看看:
對於這個結果,我們按剛才第乙個例子我所分析的過程來分析這段**,得到的是10;
故當我們將#pragma pack的n值小於所有
資料成員
長度的時候,結果將改變
。
為什麼要記憶體對齊?
cpu訪問非對齊的記憶體時為何需要多次讀取再拼接?首先簡單說一下何為記憶體對齊。例如,當cpu需要取4個連續的位元組時,若記憶體起始位置的位址可以被4整除,那麼我們稱其對齊訪問。反之,則為未對齊訪問。比如從位址0xf1取4位元組就是非對齊 位址 訪問。簡單的看來,對於乙個資料匯流排寬度為32位的cp...
什麼是記憶體對齊?為什麼要記憶體對齊?
要了解為什麼要記憶體對齊,首先我們要了解什麼是記憶體對齊 typedef struct a typedef struct b 分別對他們求大小,sizeof a sizeof b 我們所得到的結果是不同的,sizeof a 24而sizeof b 16為什麼會產生不一樣的結果呢?這是非常簡單的乙個例...
C語言 C 為什麼要記憶體對齊
例一 struct aa 例二 struct aa 首先請告訴我,例 一 例二對應的空間大小分別是多少?答案是 12位元組 8位元組。這是為什麼呢?明明有相同的成員,可是為什麼記憶體大小就不一樣呢?這就是接下看來我們要討論的記憶體對其問題了。將每乙個資料的起始位置,在記憶體的對其位置處。無論如何,為...