C C 資料對齊

2021-07-23 21:03:06 字數 2285 閱讀 2325

data alignment

關於資料對齊問題,現在多多少少有了一些接觸,簡單地說下自己的看法。

1、對齊的背景

大端和小端的問題有必要在這裡介紹一下,計算機裡面每個位址單元對應著乙個位元組,乙個位元組為8bit,對於位數大於8位的處理器來說,暫存器的寬度是大於乙個位元組的,例如16bit的short型變數x,在記憶體中的位址是0x0010,x的值為0x1122,0x11為高位元組,0x22為低位元組,常用的x86結構是小端模式,很多arm,dsp都是小端模式,而keil c51則為大端模式。記憶體空間是按照byte進行劃分的,理論上對任何型別的變數的訪問可以從任何位址開始,但實際上訪問特定變數的時候經常在特定的記憶體位址訪問,這就需要各型別的資料按照一定的規則在空間上排列,而不是順序排列,這就是對齊。

2、對齊的原因

不同硬體平台對儲存空間的處理是有很大不同的,一些平台對某些特定型別的資料只能從某些特定位址開始訪問。其他平台可能沒有這種情況, 但是最常見的是如果不按照適合其平台的要求對資料存放進行對齊,會在訪問效率上帶來損失。比如有些平台每次讀都是從偶位址開始,如果乙個int型(假設為 32位)如果存放在偶位址開始的地方,那麼乙個讀週期就可以讀出,而如果存放在奇位址開始的地方,就可能會需要2個讀週期,並對兩次讀出的結果的高低 位元組進行拼湊才能得到該int資料。顯然在讀取效率上下降很多。這也是空間和時間的博弈。

3、對齊的實現

通常我們在寫**的時候是不需要考慮對齊的影響的,都是依賴編譯器來為我們選擇適合的對齊策略,我們也可以通過傳遞給編譯器預編譯指令來指定資料對齊的方法。

以struct資料結構的sizeof方法為例,環境是mac os x 64位核心,結構體的定義如下:

struct a ;

struct b ;

#pragma pack(2)

struct c ;

#pragma pack()

#pragma pack(1)

struct d ;

#pragma pack()

int main(int argc, char** argv)

輸出:size of struct a : 8

size of struct b : 12

size of struct c : 8

size of struct d : 7

結構體中包含了4位元組長度的int乙個,1位元組長度的char乙個以及2位元組長度的short乙個。加起來所用到的記憶體空間為7個位元組,但實際使用sizeof時發現,結構體之間占用的記憶體是不一樣的。

關於對齊有幾個需要說明的:

(1)資料型別自身的對齊值:基本資料型別的自身對齊值,char型別為1,short型別為2,int,float,double為4;

(2)指定對齊值:#pragma pack(value)時的指定對齊值value;

(3)結構體或者類的自身對齊值:其成員中自身對齊值最大的那個值;

(4)資料成員、結構體和類的有效對齊值:自身對齊值或指定對齊值中較小值。

對於乙個具體的資料結構的成員和其自身的對齊方式,有效對齊值n將最終決定資料存放位址的方式的值,對齊在n上就意味著資料「存放的起始位址%n=0」,

下面來針對上面的例子進行分析:

struct b ;

假設b從位址空間0x0000開始,預設的對齊值是4(這裡有個問題想請教大家,我的是64位的核心,但是測試我的預設對齊方式為4),第乙個成員變數b的自身對齊值為1,比預設值小所以有效對齊值為1,存放位址0x0000%1=0,第二個成員變數a,自身對齊值為4,存放的起始位址為0x0004到0x0007這個4個連續的位元組空間中,0x0004%4=0,第三個變數c,自身對齊值為2,存放的起始位址為0x0008到0x0009,位址同樣符合要求。結構體b的自身對齊值為變數中的最大對齊值(b)4,(10+2)%4=0,所以0x000a到0x000b也是被結構體b占用。

記憶體中的示意圖:

b - - -

a a a a

c c#pragma pack(2)

struct c ;

#pragma pack()

第乙個變數b的自身對齊值為1,指定對齊值為2,有效對齊值為1,b存放在0x0000,a的自身對齊值為4,大於指定對齊值,所有有效的對齊值為2,a占有的位元組為0x0002、0x0003、0x0004、0x0005四個連續位元組中,c的自身對齊值為2,所以有效對齊值也是2,順序存放在0x0006、0x0007。結構體c的自身對齊值為4,所以有效對齊值為2,8%2=0。

記憶體中的示意圖:

b -a a

a ac c

其實想到記憶體中的示意圖一切都會簡單很多。

c c 資料對齊

為了避免混淆,做如下規定,以下 若不加特殊說明都執行於32位平台,結構體的預設對齊值是8,各資料型別所佔位元組數分別為 char佔乙個位元組 int佔四個位元組 double佔八個位元組。請問下面的結構體大小是多少?struct test 複製 這個呢?struct test1 複製 在公布答案之前...

C C 資料對齊

為了避免混淆,做如下規定,以下 若不加特殊說明都執行於32位平台,結構體的預設對齊值是8,各資料型別所佔位元組數分別為 char佔乙個位元組 int佔四個位元組 double佔八個位元組。請問下面的結構體大小是多少?struct test 這個呢?struct test1 在公布答案之前先看一下對齊...

C C 資料對齊

為了避免混淆,做如下規定,以下 若不加特殊說明都執行於32位平台,結構體的預設對齊值是8,各資料型別所佔位元組數分別為 char佔乙個位元組 int佔四個位元組 double佔八個位元組。請問下面的結構體大小是多少?struct test 這個呢?struct test1 在公布答案之前先看一下對齊...