C/C++—— 内存字节对齐规则

内存对齐规则:

1.数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。

比如:

struct s1{
        char a;
        short b;
        double c;
};

该结构体的大小为16个字节。首先a占有1个字节,a从偏移量为0处开始存放。b为short类型,大小为2,所以b从偏移量为2处开始存放。那么偏移量为1处没有存放数据。c大小为8个字节,所以c从偏移量为8处开始存放。所以该结构体占有16个字节。如果c大小为4个字节,所以c从偏移量为4处开始存放。所以该结构体占有8个字节。

2.结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct s2里存有struct s1,s1里有char,int ,double等元素,那s1应该从8的整数倍开始存储.)

struct s1{
        char a;
        short b;
        double c;
};

struct s2{
        char d;
        struct s1 s11;
};

结构体s1占用16个字节空间。s1中最大元素的大小为8个字节,所有该结构体应该从8个整数倍地址开始存储,前面只有一个字节的d变量。所有s1结构体应该从偏移量为8处开始存放。所以该结构体占有8+16=24个字节。

3.结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍.不足的要补齐.

struct s3{
        char a;
        double b;
        short c;    
};

结构体s3占用24个字节空间。a从偏移量为0处开始存放。b从偏移量为8处开始存放。c从偏移量为16处开始存放(占用两个字节)。貌似是18个字节啊,但是要满足规则3,结构体的大小必须是内部最大成员的整数倍,也就是应该是8个整数倍,最小只能是24。

实例源代码:

#include <iostream>
using namespace std;
//#pragma pack(4)
//大小为16个字节,参考第一个规则
struct s1{
    char a;
    short b;
    double c;
};

//大小为24个字节,参考第二个规则
struct s2{
    char d;
    struct s1 s11;
};

//大小为24个字节,参考第三个规则
struct s3{
    char a;
    double b;
    short c;
};


int main()
{
    cout << "sizeof(s1) = " << sizeof(struct s1) << endl;
    cout << "sizeof(s2) = " << sizeof(struct s2) << endl;
    cout << "sizeof(s3) = " << sizeof(struct s3) << endl;

    return 0;
}

输出为:
sizeof(s1) = 16
sizeof(s2) = 24
sizeof(s3) = 24

#pragma pack(n)简单介绍:

编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式。
n字节对齐就是说变量存放的起始地址的偏移量有两种情况:
第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式。默认对齐方式就是上面的三个规则。
第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。

结构的总大小也有个约束条件,分下面两种情况:
如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。

比如上面的例子我按 #pragma pack(4),以4字节对齐的方式得到下面的结果。

struct s1{
        char a;
        short b;
        double c;
};

占有2+2+8 = 12字节。总大小必须是4的整数倍。

struct s2{
        char d;
        struct s1 s11;
};

占有4+12 = 16字节。

struct s3{
        char a;
        double b;
        short c;    
};

占有4+8+4 = 16字节。

实例源代码:

#include <iostream>
using namespace std;
#pragma pack(4)
//大小为16个字节,参考第一个规则
struct s1{
    char a;
    short b;
    double c;
};

//大小为24个字节,参考第二个规则
struct s2{
    char d;
    struct s1 s11;
};

//大小为24个字节,参考第三个规则
struct s3{
    char a;
    double b;
    short c;
};


int main()
{
    cout << "sizeof(s1) = " << sizeof(struct s1) << endl;
    cout << "sizeof(s2) = " << sizeof(struct s2) << endl;
    cout << "sizeof(s3) = " << sizeof(struct s3) << endl;

    return 0;
}

输出:
sizeof(s1) = 12
sizeof(s2) = 16
sizeof(s3) = 16

你可能感兴趣的:(内存对齐)