C語言 記憶體中結構體位元組對齊

2021-09-30 09:11:32 字數 3251 閱讀 1196

一、位元組對齊作用和原因:

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

二、位元組對齊規則:

四個重要的概念:

1.資料型別自身的對齊值:對於char型的資料,其自身對齊值為1,對於short型為2,對於int,float,double型別,其自身對齊值為4個位元組。

2.結構體或者類的自身對齊值:其成員中自身對齊值最大的那個值。

3.指定對齊值:#pragma pack (value)時指定的對齊value。

4.資料成員、結構體和類的有效對齊值:自身對齊值和指定對齊值中小的那個值。

補充:1).每個成員分別按自己的方式對齊,並能最小化長度。

2).複雜型別(如結構)的預設對齊方式是它最長的成員的對齊方式,這樣在成員是複雜型別時,可以最小化長度。

3).對齊後的長度必須是成員中最大的對齊引數的整數倍,這樣在處理陣列時可以保證每一項都邊界對齊。

#pragma pack(1)

struct test

#pragma pack()

//sizeof(test)=13;

class test1;

//sizeof(test1)=1;

/* 註明:

1、結構或者類中的靜態成員不對結構或者類的大小產生影響,因為靜態變數的儲存位置與結構或者類的例項位址無關;

2、沒有成員變數的結構或類的大小為1,因為必須保證結構或類的每乙個例項在記憶體中都有唯一的位址。*/

示例:

//分析下面的例子c:

//#pragma pack (2) /*指定按2位元組對齊*/

struct c

;#pragma pack () //恢復對齊狀態

/*第乙個變數b的自身對齊值為1,指定對齊值為2,所以,其有效對齊值為1,假設c從0x0000開始,那麼b存放在0x0000,符合0x0000%1 = 0;

第二個變數,自身對齊值為4,指定對齊值為2,所以有效對齊值為2,所以順序存放在0x0002、0x0003、0x0004、0x0005四個連續的位元組空間中,符合0x0002%2=0。

第三個變數c的自身對齊值為2,所以有效對齊值為2,順序在0x0006、0x0007中,符合0x0006%2=0。

所以從0x0000到0x0007共八字節存放的是struct c的變數。又struct c的自身對齊值為4,所以struct c的有效對齊值為2。

又8%2=0,struct c只占用0x0000到0x0007的八個位元組。所以sizeof(struct c)=8。

如果把上面的#pragma pack(2)改為#pragma pack(4),那麼我們可以得到結構的大小為12。

*/

//再看下面這個例子

//#pragma pack(8)

struct s1

;struct s2 ;

#pragma pack()

sizeof(s2)結果為24.

/*s1中:

成員a是1位元組預設按1位元組對齊,指定對齊引數為8,這兩個值中取1,a按1位元組對齊;

成員b是4個位元組,預設是按4位元組對齊,這時就按4位元組對齊,所以sizeof(s1)應該為8;

s2 中:

c和s1中的a一樣,按1位元組對齊,

d 是個結構,它是8個位元組,它按什麼對齊呢?對於結構來說,它的預設對齊方式就是它的所有成員使用的對齊引數中最大的乙個,s1的就是4.所以,成員d就是按4位元組對齊.

成員e是8個位元組,它是預設按8位元組對齊,和指定的一樣,所以它對到8位元組的邊界上,這時,已經使用了12個位元組了,所以又新增了4個位元組的空,從第16個位元組開始放置成員e;

長度為24,已經可以被8(成員e按8位元組對齊)整除.一共使用了24個位元組.

a bs1的記憶體布局:11**,1111,

c s1.a s1.b d

s2的記憶體布局:1***,11**,1111,****11111111

*/

三、針對位元組對齊,我們在程式設計中如何考慮?

如果在程式設計的時候要考慮節約空間的話,那麼我們只需要假定結構的首位址是0, 然後各個變數按照上面的原則進行排列即可,基本的原則就是把結構中的變數按照型別大小從小到大宣告,儘量減少中間的填補空間。還有一種就是為了以空間換取時間的效率,我們顯示的進行填補空間進行對齊,比如:有一種使用空間換時間做法是顯式的插入reserved成員:

struct a

;reserved成員對我們的程式沒有什麼意義,它只是起到填補空間以達到位元組對齊的目的,當然即使不加這個成員通常編譯器也會給我們自動填補對齊,我們自己加上它只是起到顯示的提醒作用。

四、位元組對齊可能帶來的隱患

**中關於對齊的隱患,很多是隱式的。比如在強制型別轉換的時候。例如:

unsigned int i = 0x12345678;

unsigned char *p = null;

unsigned short *p1 = null;

p=&i;

*p=0x00;

p1=(unsigned short*)(p+1);

*p1=0x0000;

最後兩行**,從奇數邊界去訪問unsigned short型變數,顯然不符合對齊的規定。在x86上,類似的操作只會影響效率,但是在mips或者sparc上,可能就是乙個error,因為它們要求位元組必須對齊。

五、如何查詢與位元組對齊方面的問題

如果出現對齊或者賦值問題首先檢視

1.編譯器設定的對齊值

2.看這種體系本身是否支援非對齊訪問

3.如果支援看設定了對齊與否,如果沒有則看訪問時需要加某些特殊的修飾來標誌其特殊訪問操作。

記憶體中結構體位元組對齊

記憶體的對齊問題。柑橘還是沒能理解好。轉一篇文章放著看看。一 位元組對齊作用和原因 對齊的作用和原因 各個硬體平台對儲存空間的處理上有很大的不同。一些平台對某些特定型別的資料只能從某些特定位址開始訪問。比如有些架構的cpu在訪問乙個沒有進行對齊的變數的時候會發生錯誤,那麼在這種架構下程式設計必須保證...

C語言結構體 位元組對齊

目的 犧牲一點空間,換時間的效率 cpu執行效率 最終結構體大小一定是4的倍數 32bit系統 結構體裡成員變數順序不一致,也會影響結構體的大小 資料型別 32位機大小 位元組 64位機大小 位元組 char11 short22 int4 4long48 指標型別48 double88 float4...

C語言結構體的位元組對齊

在c語言中,結構是一種復合資料型別,其構成元素既可以是基本資料型別 如int long float等 的變數,也可以是一些復合資料型別 如陣列 結構 聯合等 的資料單元。在結構中,編譯器為結構的每個成員按其自然對界 alignment 條件分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存,第...