在c語言面試和考試中經常會遇到記憶體位元組對齊的問題。今天就來對位元組對齊的知識進行小結一下。
首先說說為什麼要對齊。為了提高效率,計算機從記憶體中取資料是按照乙個固定長度的。以32位機為例,它每次取32個位,也就是4個位元組(每位元組8個位,計算機基礎知識,別說不知道)。位元組對齊有什麼好處?以int型資料為例,如果它在記憶體中存放的位置按4位元組對齊,也就是說1個int的資料全部落在計算機一次取數的區間內,那麼只需要取一次就可以了。如圖a-1。如果不對齊,很不巧,這個int資料剛好跨越了取數的邊界,這樣就需要取兩次才能把這個int的資料全部取到,這樣效率也就降低了。
圖:a-1
圖:a-2
記憶體對齊是會浪費一些空間的。但是這種空間上得浪費卻可以減少取數的時間。這是典型的一種以空間換時間的做法。空間與時間孰優孰略這個每個人都有自己的看法,但是c語言既然採取了這種以空間換時間的策略,就必然有它的道理。況且,在儲存器越來越便宜的今天,這一點點的空間上的浪費就不算什麼了。
需要說明的是,位元組對齊不同的編譯器可能會採用不同的優化策略,以下以gcc為例講解結構體的對齊.
一、原則:
1.若沒有指定有效對齊值,結構體內成員按自身按自身長度自對齊。
自身長度,如char=1,short=2,int=4,double=8,。所謂自對齊,指的是該成員的起始位置的記憶體位址必須是它自身長度的整數倍。如int只能以0,4,8這類的位址開始 2.
若指定了有效對齊值,則按有效對齊值對齊。
3.結構體的總大小為結構體的有效對齊值的整數倍
當未明確指定有效對齊位時,以結構體中最長的成員的長度為其有效值;
結構體的有效對齊值的確定:
2)當用#pragma pack(n)指定時,
成員將在作為n
的倍數或成員的大小的倍數的邊界(以較小者為準)上對齊
。(這句是官方的話,這裡意思是:每個成員自身的位元組大小與n比較,較少者成為每個成員自身的有效對齊值)
3)當用
__attribute__ ((__packed__))
指定長度時,強制按照此值為結構體的有效對齊值
二、例子 1。
struct aaaa
結果,sizeof(aa)=12
何解?首先假設結構體內存起始位址為0,那麼位址的分布如下
0 a
1 2
34 b
5 b
6 b
7 b
8 c 9
10 11
char的字對齊長度為1,所以可以在任何位址開始,但是,int自對齊長度為4,必須以4的倍數字址開始。所以,儘管1-3空著,但b也只能從4開始。再加上c後,整個結構體的總長度為9,結構體的有效對齊值為其中最大的成員即int的長度4,所以,結構體的大小向上擴充套件到12,即9-11的位址空著。 2.
struct aaaa
sizeof(aa)=8,為什麼呢
0 a
1 c 2
34 b
5 b
6 b
7 b
因為c為char型別,字對齊長度為1,所以可以有效的利用1-3間的空格。看見了吧,變數定義的位置的不同時有可能影響結構體的大小的哦!
3. #pragma pack(2)
struct aaaa
sizeof(aa)=8,
為什麼呢?a到c只佔7位元組長度,因為結構體的有效對齊長度在pack指定的2和int的4中取
較小的值2。故取2的倍數8。
如果當pack指定為8呢?那就仍然按4來對齊,結果仍然是12。
4.struct aa__attribute__((__8__))aa
sizeof(aa)=16,)
為市民?其實a到c仍然只佔9位元組長度,但結構體以8對齊,故取8的倍數16.
如果其指定2,則結果為10
如果pragma pack和__attribute__ 同時指定呢?以__attribute__ 的為準。
需要說明的是,不管pragma pack和__attribute__如何指定,結構體內部成員的自對齊仍然按照其自身的對齊值。
另外,不同的編譯器可能會對記憶體的分布進行優化,
例如有些編譯器會把立體1中的程式優化成例題2的樣子。但這屬於編譯器的問題,
這裡不做詳細討論。如果要作為程式設計的參考的話,最好當做編譯器不會做優化,
盡量在保持**清晰的情況下,自己手動將例題1優化成例題2的樣子。
如果是做題的話,按照以上原則做就可以了,不用考慮不同編譯器的特性。
本篇是筆者從各路大咖的部落格學習後,經過實踐和官方文件查閱,多次修改後的結果,雖然已經多次修改,但是仍然
不保證100%正確,所以只作大家學習記憶體位元組對齊問題的參考
c 記憶體中位元組對齊問題詳解
c 記憶體中位元組對齊問題詳解 一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個...
c 記憶體中位元組對齊問題詳解
一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的...
c 記憶體中位元組對齊問題詳解
c 記憶體中位元組對齊問題詳解 2008年03月11日 星期二 17 15 一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料...