結構體對齊方式

2022-05-04 01:42:11 字數 2945 閱讀 2410

對齊的作用和原因:各個硬體平台對儲存空間的處理上有很大的不同。一些平台對某些特定型別的資料只能從某些特定位址開始訪問。其他平台可能沒有這種情況,但是最常見的是如果不按照適合其平台要求對資料存放進行對齊,會在訪問效率上帶來損失。

語法:#pragma pack( [show] | [push | pop] [, identifier], n )

在不指定對齊方式時 編譯器預設大小為8

可以通過命令 #pragma pack (show) 檢視

那就從預設的開始說起,由於預設是8 ,結構體如下

typedef struct test_s

{char b;

int a;

short c;

sizeof(test_s) = ?   應該是12,為何?

原因:假設test_s從位址空間0x0000開始存放。沒有定義指定對齊值,該值預設為8。

第乙個成員變數b的自身對齊值是1,比指定或者預設指定對齊值8小,所以其有效對齊值為1,所以其存放位址0x0000符合0x0000%1=0.

第二個成員變數a,其自身對齊值為4,比指定或者預設指定對齊值8小,所以其有效對齊值為4,所以只能存放在起始位址為0x0004到0x0007這四個連續的位元組空間中,符合0x0004%4=0, 且緊靠第乙個變數。

第三個變數c,自身對齊值為2,比指定或者預設指定對齊值8小,所以其有效對齊值為2,可以存放在0x0008到0x0009這兩個位元組空間中,符合0x0008%2=0。所以從0x0000到0x0009存放的都是b內容。

再看資料結構b的自身對齊值為其變數中最大對齊值(這裡是b)所以就是4,所以結構體的有效對齊值也是4。根據結構體圓整的要求,0x0009到0x0000=10位元組,(10+2)%4=0。所以0x0000a到0x000b也為結構體b所占用。故b從0x0000到0x000b共有12個位元組,sizeof(struct b)=12;

***************===分割線******************************==

重新指定對齊大小

#pragma pack(push)

#pragma pack(2)

typedef struct test_s

{char b;

int a;

short c;

#pragma pack(pop)

sizeof(test_s) = ?   應該是8,為何?

原因:假設test_s從位址空間0x0000開始存放。指定對齊值為2。

第乙個成員變數b的自身對齊值是1,比指定或者預設指定對齊值2小,所以其有效對齊值為1,所以其存放位址0x0000符合0x0000%1=0.

第二個成員變數a,其自身對齊值為4,比指定或者預設指定對齊值2大,所以其有效對齊值為2,所以只能存放在起始位址為0x0002到0x0005這四個連續的位元組空間中,符合0x0002%2=0, 且緊靠第乙個變數。

第三個變數c,自身對齊值為2,與指定或者預設指定對齊值2一樣,所以其有效對齊值為2,可以存放在0x0006到0x0008這兩個位元組空間中,符合0x0006%2=0。所以從0x0000到0x0008存放的都是b內容。

再看資料結構b的自身對齊值為其變數中最大對齊值(這裡是b)所以就是4,但結構體的有效對齊值是2。根據結構體圓整的要求,0x0008到0x0000=8位元組,(8)%2=0。所以b從0x0000到0x0008共有8個位元組,sizeof(struct b)=8;

***************===分割線******************************==

重新指定對齊大小

#pragma pack(push)

#pragma pack(1)

typedef struct test_s

{char b;

int a;

short c;

#pragma pack(pop)

sizeof(test_s) = ?   應該是7,為何?

原因:假設test_s從位址空間0x0000開始存放。指定對齊值為1。

第乙個成員變數b的自身對齊值是1,與指定或者預設指定對齊值1一樣,所以其有效對齊值為1,所以其存放位址0x0000符合0x0000%1=0.

第二個成員變數a,其自身對齊值為4,比指定或者預設指定對齊值1大,所以其有效對齊值為1,所以只能存放在起始位址為0x0001到0x0004這四個連續的位元組空間中,符合0x0001%1=0, 且緊靠第乙個變數。

第三個變數c,自身對齊值為2,比指定或者預設指定對齊值1大,所以其有效對齊值為1,可以存放在0x0005到0x0007這兩個位元組空間中,符合0x0005%1=0。所以從0x0000到0x0007存放的都是b內容。

再看資料結構b的自身對齊值為其變數中最大對齊值(這裡是b)所以就是4,但結構體的有效對齊值是1。根據結構體圓整的要求,0x0007到0x0000=7位元組,(7)%1=0。所以b從0x0000到0x0007共有7個位元組,sizeof(struct b)=7;

********************===分割線***************===

現在思路是否清晰一些呢,現在如果在增加乙個結構體成員 在看看什麼效果

#pragma pack(push)

#pragma pack(2)

typedef struct test_s

{char b;

char e;

int a;

short c;

#pragma pack(pop)

sizeof(test_s) = ?   應該是8,為何?

增加了乙個成員 在長度沒變。如果指定對齊大小為4呢 ?sizeof(test_s) = ?   應該是12

根據上面的理論應該都可以推算出來的~

總結一下:

1:如果沒指定對齊大小 ,那就按照預設大小對齊,預設值大小為多少可以通過命令檢視,前面已經提到了。

2:如果指定了對齊大小,那就要看結構體裡的成員大小與指定大小比較,按照值較小的對齊。

3:計算大小的同時 要注意結構體的取整要求。

結構體對齊方式詳解

1 平台原因 移植原因 不是所有的硬體平台都能訪問任意位址上的任意資料的 某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。2 效能原因 資料結構 尤其是棧 應該盡可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問 而對齊的記憶體訪問僅需要一次訪問...

結構體對齊計算方式

結構體的大小也不是成員型別大小的簡單相加。需要考慮到系統在儲存結構體變數時的位址對齊問題。由於儲存變數位址對齊的問題,結構體大小計算必須滿足兩條原則 一 結構體成員的偏移量必須是成員大小的整數倍 0被認為是任何數的整數倍 二 結構體大小必須是所有成員大小的整數倍 陣列除外,結構體中的結構體按單個變數...

有關結構體位元組對齊方式

今天偶然碰到對如下兩個結構體進行sizeof 運算 struct example1 struct example2 在計算機上執行後得到分別為24,16,網上查了一下,得到如下理解 1.計算方式 sizeof struct offsetof last item sizeof last item si...