位元組對齊主要是為了提高記憶體的訪問效率,比如intel 32為cpu,每個匯流排週期都是從偶地址開始讀取32位的記憶體資料,如果資料存放地址不是從偶數開始,則可能出現需要兩個匯流排週期才能讀取到想要的資料,因此需要在記憶體中存放資料時進行對齊。
通常我們說位元組對齊很多時候都是說struct結構體的記憶體對齊,比如下面的結構體:
在32位機器上char 佔1個位元組,int 佔4個位元組,short佔2個位元組,一共佔用7個位元組.但是實際真的是這樣嗎?
我們先看下面程式的輸出:
測試輸出的結果是A: 12, 比計算的7多了5個位元組。這個就是因為編譯器在編譯的時候進行了記憶體對齊導致的。
記憶體對齊主要遵循下面三個原則:
其實這裡有點不嚴謹,編譯器在編譯的時候是可以指定對齊大小的,實際使用的有效對齊其實是取指定大小和自身大小的最小值,一般預設的對齊大小是4。
再回到上面的例子,如果預設的對齊大小是4,結構體a的其實地址為0x0000,能夠被最寬的資料成員大小(這裡是int, 大小為4,有效對齊大小也是4)整除,姑char a的從0x0000開始存放佔用一個位元組即0x0000~0x0001,然後是int b,其大小為4,故要滿足2,需要從0x0004開始,所以在char a後填充三個位元組,因此a對齊後佔用的空間是0x0000~0x0003,b佔用的空間是0x0004~0x0007, 然後是short c其大小是2,故從0x0008開始佔用兩個位元組,即0x0008~0x000A。 此時整個結構體佔用的空間是0x0000~0x000A, 佔用11個位元組,11%4 != 0, 不滿足第三個原則,所以需要在後面補充一個位元組,即最後記憶體對齊後佔用的空間是0x0000~0x000B,一共12個位元組。
位元組對齊主要是為了提高記憶體的訪問效率,比如intel 32為cpu,每個匯流排週期都是從偶地址開始讀取32位的記憶體資料,如果資料存放地址不是從偶數開始,則可能出現需要兩個匯流排週期才能讀取到想要的資料,因此需要在記憶體中存放資料時進行對齊。
通常我們說位元組對齊很多時候都是說struct結構體的記憶體對齊,比如下面的結構體:
在32位機器上char 佔1個位元組,int 佔4個位元組,short佔2個位元組,一共佔用7個位元組.但是實際真的是這樣嗎?
我們先看下面程式的輸出:
測試輸出的結果是A: 12, 比計算的7多了5個位元組。這個就是因為編譯器在編譯的時候進行了記憶體對齊導致的。
記憶體對齊主要遵循下面三個原則:
結構體變數的起始地址能夠被其最寬的成員大小整除結構體每個成員相對於起始地址的偏移能夠被其自身大小整除,如果不能則在前一個成員後面補充位元組結構體總體大小能夠被最寬的成員的大小整除,如不能則在後面補充位元組其實這裡有點不嚴謹,編譯器在編譯的時候是可以指定對齊大小的,實際使用的有效對齊其實是取指定大小和自身大小的最小值,一般預設的對齊大小是4。
再回到上面的例子,如果預設的對齊大小是4,結構體a的其實地址為0x0000,能夠被最寬的資料成員大小(這裡是int, 大小為4,有效對齊大小也是4)整除,姑char a的從0x0000開始存放佔用一個位元組即0x0000~0x0001,然後是int b,其大小為4,故要滿足2,需要從0x0004開始,所以在char a後填充三個位元組,因此a對齊後佔用的空間是0x0000~0x0003,b佔用的空間是0x0004~0x0007, 然後是short c其大小是2,故從0x0008開始佔用兩個位元組,即0x0008~0x000A。 此時整個結構體佔用的空間是0x0000~0x000A, 佔用11個位元組,11%4 != 0, 不滿足第三個原則,所以需要在後面補充一個位元組,即最後記憶體對齊後佔用的空間是0x0000~0x000B,一共12個位元組。