1. 程式人生 > 其它 >C++中struct大小的確定

C++中struct大小的確定

結構體是一種複合資料型別,通常編譯器會自動的進行其成員變數的對齊,以提高資料存取的效率。

在預設情況下,編譯器為結構體的成員按照自然對齊(natural alignment)的方式分配儲存空間,各個成員按照其宣告順序在儲存器中順序儲存。自然對齊是指按照結構體中成員size最大的對齊。

#pragma pack(n) // 用來指定結構體的對齊方式。

預設對齊方式

在預設對齊方式下,結構體成員的記憶體分配滿足下面三個條件

  1. 結構體第一個成員的地址和結構體的首地址相同
  2. 結構體每個成員地址相對於結構體首地址的偏移量(offset)是該成員大小的整數倍,如果不是則編譯器會在成員之間新增填充位元組(internal adding)。
  3. 結構體總的大小要是其成員中最大size的整數倍,如果不是編譯器會在其末尾新增填充位元組(trailing padding)。

指定對齊方式

可以使用#pragma pack(N)來指定結構體成員的對齊方式
對於指定的對齊方式,其成員的地址偏移以及結構體的總的大小也有下面三個約束條件

  1. 結構體第一個成員的地址和結構體的首地址相同
  2. 結構體每個成員的地址偏移需要滿足:N大於等於該成員的大小,那麼該成員的地址偏移需滿足預設對齊方式(地址偏移是其成員大小的整數倍);N小於該成員的大小,那麼該成員的地址偏移是N的整數倍
  3. 結構體總的大小需要是N的整數倍,如果不是需要在結構體的末尾進行填充。
  4. 如果N大於結構體成員中最大成員的大小,則N不起作用,仍然按照預設方式對齊。

說明

  1. 在使用#pragma pack設定對齊方式一定要是2的整數冪,也就是(1,2,4,8,16,...),不然不起作用的,仍然按照預設方式對齊。
  2. 當結構體中有其他的結構體作為成員時,計算最大成員是不能把結構體成員作為一個整體來計算,要看其每個成員的大小。

示例

預設對齊方式

#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;
}