C++中struct大小的確定
阿新 • • 發佈:2021-08-11
結構體是一種複合資料型別,通常編譯器會自動的進行其成員變數的對齊,以提高資料存取的效率。
在預設情況下,編譯器為結構體的成員按照自然對齊(natural alignment)的方式分配儲存空間,各個成員按照其宣告順序在儲存器中順序儲存。自然對齊是指按照結構體中成員size最大的對齊。
#pragma pack(n) // 用來指定結構體的對齊方式。
預設對齊方式
在預設對齊方式下,結構體成員的記憶體分配滿足下面三個條件
- 結構體第一個成員的地址和結構體的首地址相同
- 結構體每個成員地址相對於結構體首地址的偏移量(offset)是該成員大小的整數倍,如果不是則編譯器會在成員之間新增填充位元組(internal adding)。
- 結構體總的大小要是其成員中最大size的整數倍,如果不是編譯器會在其末尾新增填充位元組(trailing padding)。
指定對齊方式
可以使用#pragma pack(N)
來指定結構體成員的對齊方式
對於指定的對齊方式,其成員的地址偏移以及結構體的總的大小也有下面三個約束條件
- 結構體第一個成員的地址和結構體的首地址相同
- 結構體每個成員的地址偏移需要滿足:N大於等於該成員的大小,那麼該成員的地址偏移需滿足預設對齊方式(地址偏移是其成員大小的整數倍);N小於該成員的大小,那麼該成員的地址偏移是N的整數倍。
- 結構體總的大小需要是N的整數倍,如果不是需要在結構體的末尾進行填充。
- 如果N大於結構體成員中最大成員的大小,則N不起作用,仍然按照預設方式對齊。
說明
- 在使用#pragma pack設定對齊方式一定要是2的整數冪,也就是(1,2,4,8,16,...),不然不起作用的,仍然按照預設方式對齊。
- 當結構體中有其他的結構體作為成員時,計算最大成員是不能把結構體成員作為一個整體來計算,要看其每個成員的大小。
示例
預設對齊方式
#include <iostream> // #pragma pack(2) struct s1 { int i1; char c1; double d1; }; struct s2 { char c2; s1 s11; }; using namespace std; int main() { cout << offsetof(s2, s11) << endl; // 8 cout << sizeof(s1) << endl; // 16 cout << sizeof(s2) << endl; // 24 return 0; }
指定對齊方式
#include <iostream>
#pragma pack(2)
struct s1
{
int i1;
char c1;
double d1;
};
struct s2
{
char c2;
s1 s11;
};
using namespace std;
int main()
{
cout << offsetof(s2, s11) << endl; // 2
cout << sizeof(s1) << endl; // 14
cout << sizeof(s2) << endl; // 16
return 0;
}