1. 程式人生 > >C++中結構體的對齊方式

C++中結構體的對齊方式

在面試中,常會考到結構體的對齊方式,因此對其進行總結。

1、在沒有#pragma pack巨集的情況下

 

 
  1. struct sA{

  2. double d1;

  3. int i1;

  4. double d2;

  5. char c1;

  6. };

 原則1:每個成員按型別的大小對齊,即相對於結構體地址的成員地址能被型別大小整除.並且結構體的大小(sizeof(A))必須為成員所含型別中最大值(sizeof(double))的整數倍,不夠就補空位元組.

例1:

例如用結構體定義物件A,其第一個成員d1的型別為double,大小為8位元組,它的地址(也是A的地址)就需要能被4整除,這主要是因為為A申請記憶體時,其地址由其成員中所含的最大型別單獨申請記憶體的規則決定(A中最大型別為double),int和double型別在單獨申請記憶體時,其地址為4的整數倍。第二個成員i1的型別為int,大小為4位元組,它相對於結構體A地址(00BDF7EC)的成員地址(8)能被4整除,不需要補充空白位元組。第三個成員d2的型別為double,大小為8位元組,它相對於結構體A地址(00BDF7EC)的成員地址(12)不能被8整除,需要補充4個空白位元組。第四個成員c1的型別為char,大小為1位元組,它相對於結構體A地址(00BDF7EC)的成員地址(16)能被1整除,不需要補充空白位元組。

 原則2:結構體作為成員,型別大小按其成員所含最大型別計算。

 

 
  1. struct sB{

  2. char c1;

  3. sA sA1;

  4. };

 

例2:struct sB裡存有struct sA,其結構體成員sA1的型別大小按8位元組計算

 原則3:結構體的總大小,為其成員中所含最大型別的整數倍。在例1中即為成員d1型別(double,8)的整數倍。而在例二中即為成員sA1型別(8)的整數倍。

2、在有#pragma pack巨集的情況下

(1)#pragma pack(1),例1和例2的情況如下

可以看到其成員均按1作為其型別大小進行對齊,結構體的總大小也為1的整數倍。

 

(2)#pragma pack(2),例1和例2的情況如下

可以看到其成員均按2作為其型別大小進行對齊,結構體的總大小也為2的整數倍。

 

(3)#pragma pack(4),例1和例2的情況如下

可以看到其成員均按4作為其型別大小進行對齊,結構體的總大小也為4的整數倍。

附上程式碼

#include<stdio.h>
#include<iostream>
using namespace std;
#pragma pack(2)
struct sA{
    double d1;
    int i1;
    double d2;
    char c1;
};
struct sB{
    char c1;
    sA sA1;
};
 
int main()
{
    sA A;
    sB B;
    cout << "A的地址:" << &A << endl
        << "A.d1的地址:" << &A.d1 << endl
        << "A.i1的地址:" << &A.i1 << endl
        << "A.d2的地址:" << &A.d2 << endl
        << "A.c1的地址:" <<(void*)&A.c1 << endl
        << "A的大小:" << sizeof(A) << endl;
 
    cout << "B的地址:" << &B << endl
        << "B.c1的地址:" <<(void*) &B.c1 << endl
        << "B.sA1的地址:" << &B.sA1 << endl
        << "B的大小:" << sizeof(B) << endl;
    while (1);    
    return 0;
}