一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的大小之和。
#include <iostream>
using namespace std;
struct A
{
char a;
int b;
double c;
};
struct B
{
char a;
double c;
int b;
};
int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
return 0;
}
运行后其结果如下:
明明是相同的结构体,可为什么其大小却不相同呢?
这里就存在内存对齐问题。
规则一:结构体中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址0开始,每一个元素放置到内存中时,它都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始。
如上图例,首先系统会将字符型变量a存入第0个字节,然后在存放整形变量b时,会以4个字节进行存储,由于第一个四字节模块已有数据,因此它会存入第二个四字节模块,也就是存入到4~8字节;同理,存放双精度型变量c时,由于其宽度为8,其存放时会以8个字节为单位存储,也就是会找到第一个空的且是8的整数倍的位置开始存储,上列中,由于头一个8字节模块已被占用,所以将c存入第二个8字节模块。
结构体B因为与结构体A两个变量的类型发生交换,其测试结果发生变化。其大小为 8+8+4=20;但运行结果为24,这就用到规则二。
== 规则二:在经过第一规则分析后,检查计算出的存储单元是否为所有元素中最宽的元素的长度的整数倍,是,则结束;若不是,则补齐为它的整数倍。==
B结构体中,我们分析完后的存储长度为20字节,不是最宽元素长度8的整数倍,因此将它补齐到8的整数倍,也就是24。
总结一下:
结构体内存对齐规则
原则1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,
第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack
指定的数值和这个数据成员自身长度中,比较小的那个进行。
原则2:结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,
结构(或联合)本身也要进行对齐,对齐将按照#pragma pack
指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
原则3:结构体作为成员:如果一个结构里有某些结构体成员,
则结构体成员要从其内部最大元素大小的整数倍地址开始存储。