1. 程式人生 > >關於結構體的記憶體對齊

關於結構體的記憶體對齊

記憶體是以位元組為單位編號,但一些硬體平臺對某些特定型別的資料只能從某些特定地址開始,比如從偶地址開始。若不按照適合其平臺的要求對資料存放進行對齊,會影響到效率。因此,在記憶體中,各型別的資料是按照一定的規則在記憶體中存放的,這就是本文要研究的對齊問題。

本文以gcc version 4.4.5,32位x86環境為例,來分析結構體中各成員如何進行對齊。

我們要注意兩個方面:1)結構體成員變數對存放的起始地址有要求。2)結構體變數佔用的總長度也有要求。

結構體對齊規則如下:

資料成員最終的存放地址:對齊在自身型別長度和pragma pack(value)指定值中較小的值上。

結構體的總長度:對齊在成員型別長度最大的值和pragma pack(value)指定值中較小的值上。

所謂“對齊在N上”,指定是“存放起始地址%N=0”

看下面幾個例子:

例1:

分析:此程式的測試環境,相當於pragma pack(4),

a 成員的起始地址是0xbfe8ff18,

char型別長度1,pragma pack(4),取小的1, 0xbfe8ff18%1=0,符合規則。

b成員,short型別長度2,pragma pack(4),取小的2,若存在地址0xbfe8ff19,則0xbfe8ff19%2餘數為1,不是0,所以只能空出一個位元組,在0xbfe8ff1a地址存放。

c成員,int型別長度4,pragma pack(4),取小的4,若存在地址0xbfe8ff1a+2,即0xbfe8ff1c處,則0xbfe8ff1c%4餘數為0,符合規則。

這樣整個結構體,佔用了記憶體的0xbfe8ff18~0xbfe8ff1f, 共8個位元組。結構體的總長度是要求“對齊在成員型別長度最大的值和pragma pack(value)指定值中較小的值上。”這裡是要求能被4除盡,8符合要求,所以sizeof(struct F)是8.

例2:

a 成員的起始地址是0xbfe8ff18,

char型別長度1,pragma pack(4),取小的1, 0xbfbb41a8%1=0。

b成員,int型別長度4,pragma pack(2),取小的2,若存在地址0xbfbb41a9,則0xbfbb41a9%2餘數為1,不是0,所以只能空出一個位元組,在0xbfbb41aa地址存放。

c成員,short型別長度2,pragma pack(2),取小的2,若存在地址0xbfbb41aa +4,即0xbfbb41ae處,則0xbfbb41ae %4餘數為0,符合規則。

這樣整個結構體,佔用了記憶體的0xbfbb41a8~0xbfbb41af, 共8個位元組。結構體的總長度是要求“對齊在成員型別長度最大的值和pragma pack(value)指定值中較小的值上。”這裡是要求能被2除盡,8符合要求,所以sizeof(struct F)是8.

例3:

具體的分析,不再重複,讀者可以和上面的例子做個比較,有了pragma pack(4)後,結構體的總長度,為12,不再是8。