ARM是32位處理器,armv4能高效的處理8,16,32位的數據,但是大多數arm處理器直接操作的是32位的數據。
地址跳變基數爲4字節即4.一次存取數據量爲32位。(硬件角度),我們一次取到的32位數據不一定是一個完整
的數據構,可能是兩個數據結構,也可能是某個數據結構的一部分,(而編譯器幫助我們將一條對數據結構操作
的C操作轉化成多條對齊的彙編指令,這些從每次取到的32位數據中獲得有用的值,合併重組而完成對一個數據結構的操作)
當對一個數據結構進行操作時,如邊界不對齊,編譯器可以將C操作轉化成多條邊界對齊的彙編操作,把結果合併、
重組來模擬對齊的操作(可見這種非對齊的存儲是非常消耗效率的)。
軟件角度,在軟件方面我們定義的數據排列方式是由編譯器決定的,根據編譯器的對稱規則進行數據排列,而常用的
數據操作指令(ARM指令中的)是以4字節爲對稱邊界進行操作的。C中允許你干預“內存對齊”。
上面已經提到了,內存對齊對處理器效率的影響,而我們關注內存對齊不外乎下面兩大原因:
1、平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取
某些特定類型的數據,否則拋出硬件異常。(平臺移植是驅動程序開發者經常需要考慮的問題)。
2、性能原因:數據結構(尤其是棧)應該儘可能地在自然邊界上對齊。原因在於,爲了訪問未對齊的內存,處理器需要
作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。(就是剛纔所提到的對效率的影響)。
下面簡要說明下內存對齊對高質量可移植代碼的重要性:
在arm處理器中如果裝載和存儲的地址與數據類型的邊界不對齊,那麼可能產生異常的結果,例如:通常C編譯器假定
指針是邊界對齊的。如果指針不是邊界對齊,那麼程序執行會產生不正確的結果。這樣,把代碼從允許邊界不對齊的
處理器移植到ARM處理器時就會出現問題。
最後再提一下對齊規則:
對齊規則
每個特定平臺上的編譯器都有自己的默認“對齊係數”(也叫對齊模數)。程序員可以通過預編譯命令#pragma pack(n)
,n=1,2,4,8,16來改變這一系數,其中的n就是你要指定的“對齊係數”。
規則:
1、數據成員對齊規則:結構(struct)(或聯合(union))的數據成員,第一個數據成員放在offset爲0的地方,以後每個數據
成員的對齊按照#pragma pack指定的數值和這個數據成員自身長度中,比較小的那個進行。
2、結構(或聯合)的整體對齊規則:在數據成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragma
pack指定的數值和結構(或聯合)最大數據成員長度中,比較小的那個進行。
3、結合1、2可推斷:當#pragma pack的n值等於或超過所有數據成員長度的時候,這個n值的大小將不產生任何效果。