例一:
struct aa
;
例二:
struct aa
;
首先請告訴我,例
一、例二對應的空間大小分別是多少?
答案是:12位元組、8位元組。這是為什麼呢?明明有相同的成員,可是為什麼記憶體大小就不一樣呢?
這就是接下看來我們要討論的記憶體對其問題了。
將每乙個資料的起始位置,在記憶體的對其位置處。
無論如何,為了提高程式的效能,資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;然而,對齊的記憶體訪問僅需要一次訪問。
乙個字或雙字運算元跨越了4位元組邊界,或者乙個四字運算元跨越了8位元組邊界,被認為是未對齊的,從而需要兩次匯流排週期來訪問記憶體。乙個字起始位址是奇數但卻沒有跨越字邊界被認為是對齊的,能夠在乙個匯流排週期中被訪問。
1、資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員的對齊按照#pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。
2、結構(或聯合)的整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大資料成員長度中,比較小的那個進行。
3、結合1、2可推斷:當#pragma pack的n值等於或超過所有資料成員長度的時候,這個n值的大小將不產生任何效果。
win32平台下的微軟c編譯器(cl.exefor 80×86)的對齊策略:
1)結構體變數的首位址是其最長基本型別成員的整數倍;
備註:編譯器在給結構體開闢空間時,首先找到結構體中最寬的基本資料型別,然後尋找記憶體位址能是該基本資料型別的整倍的位置,作為結構體的首位址。將這個最寬的基本資料型別的大小作為上面介紹的對齊模數。
2)結構體每個成員相對於結構體首位址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internal adding);
備註:為結構體的乙個成員開闢空間之前,編譯器首先檢查預開闢空間的首位址相對於結構體首位址的偏移是否是本成員的整數倍,若是,則存放本成員,反之,則在本成員和上乙個成員之間填充一定的位元組,以達到整數倍的要求,也就是將預開闢空間的首位址後移幾個位元組。
3)結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要,編譯器會在最末乙個成員之後加上填充位元組(trailing padding)。
備註:
a、結構體總大小是包括填充位元組,最後乙個成員滿足上面兩條以外,還必須滿足第三條,否則就必須在最後填充幾個位元組以達到本條要求。
b、如果結構體內存在長度大於處理器位數的元素,那麼就以處理器的倍數為對齊單位;否則,如果結構體內的元素的長度都小於處理器的倍數的時候,便以結構體裡面最長的資料元素為對齊單位。
4) 結構體內型別相同的連續元素將在連續的空間內,和陣列一樣。
為什麼要記憶體對齊
當我們聽到 記憶體對齊 這個概念時,從字面意思來看,很容易理解。那就是讓記憶體按一定規則對齊。當然 就會有人說 你這不是廢話 現在我就來說一說為什麼要記憶體對齊以及怎麼個對齊法 如何對齊 記憶體對齊 記憶體對齊 應該是 編譯器的 管轄範圍 編譯器為程式中的每個 資料單元 對於記憶體對齊問題,主要存在...
為什麼要記憶體對齊?
cpu訪問非對齊的記憶體時為何需要多次讀取再拼接?首先簡單說一下何為記憶體對齊。例如,當cpu需要取4個連續的位元組時,若記憶體起始位置的位址可以被4整除,那麼我們稱其對齊訪問。反之,則為未對齊訪問。比如從位址0xf1取4位元組就是非對齊 位址 訪問。簡單的看來,對於乙個資料匯流排寬度為32位的cp...
什麼是記憶體對齊?為什麼要記憶體對齊?
要了解為什麼要記憶體對齊,首先我們要了解什麼是記憶體對齊 typedef struct a typedef struct b 分別對他們求大小,sizeof a sizeof b 我們所得到的結果是不同的,sizeof a 24而sizeof b 16為什麼會產生不一樣的結果呢?這是非常簡單的乙個例...