1、為什麼要對結構體內存對齊?
了解計算機的人都知道,cpu是沒有辦法來儲存資料的,cpu只有計算能力。所以,儲存資料的任務就交給了記憶體。那麼,當cpu需要計算的時候,就需要從記憶體上獲取資料,記憶體上資料和位址是對應的,cpu只要知道對應資料的位址,就可以呼叫資料了。
知道了cpu必須定址之後,我們來看一下乙個結構體是怎麼定義的。
這裡,我們要對c2定址的話,直接定址即可。可是如果要對i進行定址呢,因為定址位址必須是4的整數倍,所以先從0x04定址,到0x07之後結束,還必須減去c2的位址,這是i的前半部分;並且由於i沒有完全得到,還必須從0x08開始,繼續4個位元組,然後減去0x09之後不包括i資料的位址,然後得到i的後半部分,再把前半部分和後半部分拼接得到i。由此可見,定址效率非常低下,所以必須要進行記憶體對齊,從而提高定址效率。
2、如何進行記憶體對齊呢?
記憶體對齊的規則
(1)第乙個成員在與結構體變數偏移量為0的位址處。
(2)其他成員變數要對齊到某個數字(對齊數)的整數倍的位址處。注:起始偏移量能整除對齊數,即為對齊。
(3)結構體總大小為最大對齊數(每個成員變數都有乙個對齊數)的整數倍。注:結構體內所有成員各自對齊數的最大值(包括第乙個)。
(4)如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。
(5)陣列的對齊數就是陣列內元素的型別位元組大小。
(6)結構體對齊數是結構體的最大對齊數。
3、舉例理解
知道了記憶體對齊的規則之後,我們來通過兩個例子明白如何使用上面的規則。
例1、
struct s1 ;
我們可以看到,結構體s1的位元組大小是12。為什麼呢?我們來解釋一下。
先給c1開闢空間,直接開闢1個位元組,根據規則1,偏移量是1位元組。然後給i開闢空間,這裡就不能直接開闢了,通過規則2可知,偏移量必須能整除i的對齊數,而i的對齊數是4現在偏移量是1,所以就再開闢3個位元組的空間,現在就可以給i開闢空間了,因為此時偏移量是4,能整除i的對齊數,然後在4個位元組的偏移量基礎上給i開闢4個位元組空間,現在就一共開闢了8個位元組的空間。最後給c2開闢空間,此時偏移量是8,可以整除c2的對齊數1,所以直接開闢c2的空間,1個位元組,所以是8加1等於9個位元組。然而根據規則3,結構體的大小必須能整除最大對齊數,而此時的最大對齊數是4,又因為9不能整除4,所以接著開闢3個位元組,9加3等於12。所以結構體s1的位元組大小就是12。
例2、
struct s1 ;
這裡s2裡面巢狀了乙個結構體s1,根據規則4可知,結構體的對齊數是它的最大對齊數,就s1而言,s1的對齊數就是4,s1的大小我們已經計算出是12位元組。現在,我們看s2,首先給c1開闢空間,1個位元組。然後給s1開闢空間,此時偏移量是1,s1的對齊數是4,不能整除,所以給偏移量加3,偏移量變為4,可以整除,再給s1開闢空間,4加12是16位元組。最後給d開闢空間,d的對齊數是8,大小是8位元組,此時偏移量是16,可以整除對齊數8,所以直接給d開闢空間,8加16是24位元組,根據規則3,s4的最大對齊數是8,因為24能整除8,所以s2的大小就是24位元組。
總結:
a、要理解對齊數的概念,所謂對齊數就是變數本身位元組的大小。對於結構體和陣列則不是,結構體的對齊數是最大對齊數,就是結構體內所有變數對齊數最大的那個。陣列則是陣列內的元素型別位元組大小。
b、計算結構體位元組大小時,不可以上來就給變數開闢空間,需要看此時的偏移量能否整除掉此時要開闢空間的變數的對齊數,如果能整除,就直接開闢。如果不能整除,就加位元組空間,加到可以整除,再開闢。
c、結構體的大小計算完畢後,還需要看是不是能整除結構體的最大對齊數。如果能整除,那麼此時計算出的大小就是結構體的大小,如果不是,就加位元組空間,加到可以整除,這時才是結構體的大小。
d、陣列結構體的最大對齊數是結構體的最大對齊數。
4、記憶體對齊到底是什麼?
由於硬體條件的限制,cpu只能按4個位元組進行定址。如果不進行記憶體對齊,就會出現定址效率低下的問題。總體來說:記憶體對齊就是以犧牲空間為代價,換取時間,提高定址效率。
結構體的記憶體對齊問題
在c c 筆試中,記憶體對齊問題經常考,儘管這樣,這幾年來我一直忽略了這個問題,記憶中一直是大學課本中struct與union的區別,那時候也不曾有提及過記憶體對齊,現在想起來,真是非常大的漏洞。而且很多筆試想當然的覺得struct的大小就是內部所有變數大小的和,卻不知這種錯誤的答案讓多少面試官默默...
簡單理解結構體的記憶體對齊
記憶體對齊三原則 資料成員對齊規則 結構 struct 或聯合 union 的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小或者成員的子成員大小 只要該成員有子成員,比如說是陣列,結構體等 的整數倍開始 比如int在32位機為 位元組,則要從 的整數...
區間DP,子問題的深刻理解
演算法提高 矩陣乘法 時間限制 3.0s 記憶體限制 256.0mb 問題描述 有n個矩陣,大小分別為a0 a1,a1 a2,a2 a3,a n 1 a n 現要將它們依次相乘,只能使用結合率,求最少需要多少次運算。兩個大小分別為p q和q r的矩陣相乘時的運算次數計為p q r。輸入格式 輸入的第...