記憶體對齊

記憶體對齊

記憶體對齊,是編譯器的管轄範圍,編譯器為程式中的每個數據單元安排在適當的位置上。但是C語言的一個特點就是太靈活,太強大,它允許干預記憶體對齊,如果想了解更加底層的秘密,記憶體對齊就不應該再透明了。

基本信息

對齊原因

記憶體對齊記憶體對齊
大部分的參考資料都是如是說的:
1、平台原因(移植原因):不是所有的硬體平台都能訪問任意地址上的任意數據的;某些硬體平台只能在某些地址處取某些特定類型的數據,否則拋出硬體異常。
2、性能原因:數據結構(尤其是棧)應該儘可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。

對齊規則

記憶體對齊記憶體對齊
每個特定平台上的編譯器都有自己的默認“對齊係數”(也叫對齊模數)。程式設計師可以通過預編譯命令#pragmapack(n),n=1,2,4,8,16來改變這一係數,其中的n就是你要指定的“對齊係數”。
規則:
1、數據成員對齊規則:結構(struct)(或聯合(union))的數據成員,第一個數據成員放在offset為0的地方,以後每個數據成員的對齊按照#pragmapack指定的數值和這個數據成員自身長度中,比較小的那個進行。
2、結構(或聯合)的整體對齊規則:在數據成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragmapack指定的數值和結構(或聯合)最大數據成員長度中,比較小的那個進行。
3、結合1、2可推斷:當#pragmapack的n值等於或超過所有數據成員長度的時候,這個n值的大小將不產生任何效果。
Win32平台下的微軟C編譯器(cl.exefor80×86)的對齊策略:
1)結構體變數的首地址是其最長基本類型成員的整數倍
備註:編譯器在給結構體開闢空間時,首先找到結構體中最寬的基本數據類型,然後尋找記憶體地址能是該基本數據類型的整倍的位置,作為結構體的首地址。將這個最寬的基本數據類型的大小作為上面介紹的對齊模數
2)結構體每個成員相對於結構體首地址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internaladding);
備註:為結構體的一個成員開闢空間之前,編譯器首先檢查預開闢空間的首地址相對於結構體首地址的偏移是否是本成員的整數倍,若是,則存放本成員,反之,則在本成員和上一個成員之間填充一定的位元組,以達到整數倍的要求,也就是將預開闢空間的首地址後移幾個位元組。
3)結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要,編譯器會在最末一個成員之後加上填充位元組(trailingpadding)。
備註:
a、結構體總大小是包括填充位元組,最後一個成員滿足上面兩條以外,還必須滿足第三條,否則就必須在最後填充幾個位元組以達到本條要求。
b、如果結構體記憶體在長度大於處理器位數的元素,那么就以處理器的倍數為對齊單位;否則,如果結構體內的元素的長度都小於處理器的倍數的時候,便以結構體裡面最長的數據元素為對齊單位。
4)結構體內類型相同的連續元素將在連續的空間內,和數組一樣。

相關詞條

相關搜尋

熱門詞條

聯絡我們