原文:http://msdn.microsoft.com/zh-cn/library/ms253949.aspx
翻譯:http://www.52rd.com/Blog/Detail_RD.Blog_imjacob_10489.html
很多CPU,如基於Alpha, IA-64, MIPS, 和SuperH 體系的,拒絕讀取未對齊數據。當一個程序要求其中之一的CPU讀取未對齊數據時,這時CPU會進入異常處理狀態並且通知程序不能繼續執行。舉個例子,在ARM, MIPS, 和SH硬件平臺上,當操作系統被要求存取一個未對齊數據時默認通知應用程序一個異常。
在不支持未對齊的內存訪問的硬件平臺上進行未對齊的內存訪問會遭致巨大的性能損失。
對齊
對齊是一種內存地址的特性,表現在內存地址對2的冪數取模上。例如,內存地址 0x0001103F模4結果爲3;這個地址就叫做與4n+3對齊,4指出了所選用的2的冪的值。內存地址的對齊取決於所選擇的關於2的冪值。(這個)相同的地址模8結果爲7。
一個內存地址符合表達式Xn+0 ,那麼就說該地址對齊於X。
CPU 執行指令就是對存儲於內存上的數據進行操作,這些數據在內存上是以地址爲標記的。對於地址來說,單獨的數據會有其佔用內存的字節數。如果它的地址對齊於它的字節數,那麼就稱作該數據自然對齊,否則稱爲未對齊。例如,一個標記8字節的浮點數據的地址對齊於8(即其地址滿足8n+0),那麼這個數據就自然對齊。
數據對齊的編譯處理
設備編譯器以一種防止造成數據未對齊的方式來對數據進行地址分配。
對於簡單數據類型,編譯器爲其分配的地址是數據類型字節數的倍數。因此,編譯器分配給long型變量的地址爲4的倍數,就是說以2進製表示地址的話,最後兩位爲00。
另外,編譯器以一種自然對齊每個結構成員的方式來填充結構體。參看下面的代碼裏面的結構體struct x_。
struct x_
{
char a; // 1 字節
int b; // 4 字節
short c; // 2 字節
char d; // 1 字節
} MyStruct;
編譯器填充這個結構以使其自然對齊。
例如
下面的代碼說明了編譯器是如何在內存中填充的。
//顯示內存實際狀態(佈局)
struct x_
{
char a; // 1 字節
char _pad0[3]; // 填充(3個字節)使b(下一個成員)在4字節的邊界上
int b; // 4 字節
short c; // 2 字節
char d; // 1 字節
char _pad1[1]; // 填充使X_的大小爲4的整數倍
};
兩種定義在作sizeof(struct x_)運算都會返回12字節。
第二種定義含有兩種填充成分:
❉ char _pad0[3]使得int b 在“4-字節”邊界上對齊
❉ char _pad1[1]使得結構數組struct _x bar[3]的元素對齊。
填充使得bar[3]各個元素能夠自然對齊。
下面的代碼顯示了bar[3]的內存結構: