一.記憶體對齊的初步講解
記憶體對齊可以用一句話來概括:
「資料項只能儲存在位址是資料項大小的整數倍的記憶體位置上」
例如int型別占用4個位元組,位址只能在0,4,8等位置上。
#include struct xx;
int main()
執行結果如下:
&a = ffbff5ec
&b = ffbff5e8
&c = ffbff5f0
&d = ffbff5f4
sizeof(xx) = 16
會發現b與a之間空出了3個位元組,也就是說在b之後的0xffbff5e9,0xffbff5ea,0xffbff5eb空了出來,a直接儲存在了0xffbff5ec, 因為a的大小是4,只能儲存在4個整數倍的位置上。列印xx的大小會發現,是16,有些人可能要問,b之後空出了3個位元組,那也應該是13啊?其餘的3個 呢?這個往後閱讀本文會理解的更深入一點,這裡簡單說一下就是d後邊的3個位元組,也會浪費掉,也就是說,這3個位元組也被這個結構體占用了.
二.作業系統的預設對齊係數
每 個作業系統都有自己的預設記憶體對齊係數,如果是新版本的作業系統,預設對齊係數一般都是8,因為作業系統定義的最大型別儲存單元就是8個位元組,例如 long long(為什麼一定要這樣,在第三節會講解),不存在超過8個位元組的型別(例如int是4,char是1,long在32位編譯時是4,64位編譯時是 8)。當作業系統的預設對齊係數與第一節所講的記憶體對齊的理論產生衝突時,以作業系統的對齊係數為基準。
例如:假設作業系統的預設對齊係數是4,那麼對與long long這個型別的變數就不滿足第一節所說的,也就是說long long這種結構,可以儲存在被4整除的位置上,也可以儲存在被8整除的位置上。
可以通過#pragma pack()語句修改作業系統的預設對齊係數,編寫程式的時候不建議修改預設對齊係數,在第三節會講解原因
#include #pragma pack(4)
struct xx;
#pragma pack()
int main()
列印結果為:
&a = ffbff5e4
&b = ffbff5e0
&c = ffbff5ec
&d = ffbff5f0
sizeof(xx) = 20
發現占用8個位元組的a,儲存在了不能被8整除的位置上,儲存在了被4整除的位置上,採取了作業系統的預設對齊係數。
三.記憶體對齊產生的原因
記憶體對齊是作業系統為了快速訪問記憶體而採取的一種策略,簡單來說,就是為了放置變數的二次訪問。作業系統在訪問記憶體 時,每次讀取一定的長度(這個長度就是作業系統的預設對齊係數,或者是預設對齊係數的整數倍)。如果沒有記憶體對齊時,為了讀取乙個變數是,會產生匯流排的二 次訪問。
例如假設沒有記憶體對齊,結構體xx的變數位置會出現如下情況:
struct xx;
作業系統先讀取0xffbff5e8-0xffbff5ef的記憶體,然後在讀取0xffbff5f0-0xffbff5f8的記憶體,為了獲得值c,就需要將兩組記憶體合併,進行整合,這樣嚴重降低了記憶體的訪問效率。(這就涉及到了老生常談的問題,空間和效率哪個更重要?這裡不做討論)。
這樣大家就能理解為什麼結構體的第乙個變數,不管型別如何,都是能被8整除的吧(因為訪問記憶體是從8的整數倍開始的,為了增加讀取的效率)!
C語言 記憶體對齊
寫出乙個struct,然後sizeof,你會不會經常對結果感到奇怪?sizeof的結果往往都比你宣告的變數總長度要大,這是怎麼回事呢?講講位元組對齊吧.分割線 如果體系結構是不對齊的,a中的成員將會乙個挨乙個儲存,從而sizeof a 為11。顯然對齊更浪費了空間。那麼為什麼要使用對齊呢?體 繫結構...
c語言記憶體對齊
記錄平常所學,以便回顧。c語言中存在著記憶體對齊問題,在struct儲存中尤為明顯,這裡先介紹一種情況,以後接著補充。typedef unsigned char u8 typedef unsigned short u16 typedef unsigned long u32 typedef unsig...
C語言 記憶體對齊
記憶體對齊 結構體內成員按自身長度自對齊,即按他們的起點長度必須是自身長度的整數倍對齊 如在32位系統下,int 型的開始位址必須位0,4,8,這種整形資料型別長度大小的倍數開始 結構體的總大小必須位有效對齊值的整數倍 有效對齊值的確定 當有效對齊值為明確指定時,以結構體內成員的最長者的長度為有效對...