文档介绍:对齐原则为:单字节变量无需对齐,可放在任何地址双字节变量起始地址为 2的倍数 4字节变量首地址为 4的倍数一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的宽度之和。例一: #include <iostream> using namespace std; struct X{ char a; int b; double c; }S1; void main() { cout << sizeof(S1) << endl; cout << sizeof() << endl; cout << sizeof() << endl; cout << sizeof() << endl; }比如例一中的结构体变量 S1 定义之后,经测试,会发现 sizeof(S1 )= 16 , 其值不等于 sizeof() =1、 sizeof() =4和 sizeof() =8三者之和, 这里面就存在存储对齐问题。原则一:结构体中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每一个元素放置到内存中时,它都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始(以结构体变量首地址为 0计算)。比如此例,首先系统会将字符型变量 a存入第 0个字节(相对地址,指内存开辟的首地址);然后在存放整形变量 b时,会以 4个字节为单位进行存储, 由于第一个四字节模块已有数据,因此它会存入第二个四字节模块,也就是存入到 4~8 字节;同理,存放双精度实型变量 c时,由于其宽度为 8,其存放时会以 8个字节为单位存储,也就是会找到第一个空的且是 8的整数倍的位置开始存储, 此例中,此例中,由于头一个 8字节模块已被占用,所以将 c存入第二个 8字节模块。整体存储示意图如图 1所示。考虑另外一个实例。例二: struct X{ char a; double b; intc; }S2; 在例二中仅仅是将 double 型的变量和 int型的变量互换了位置。测试程序不变,测试结果却截然不同, sizeof(S2)=24 ,不同于我们按照原则一计算出的 8+8+4=20 ,这就引出了我们的第二原则。原则二:在经过第一原则分析后,检查计算出的存储单元是否为所有元素中最宽的元素的长度的整数倍,是,则结束;若不是,则补齐为它的整数倍。例二中,我们分析完后的存储长度为 20 字节,不是最宽元素长度 8的整数倍, 因此将它补齐到 8的整数倍,也就是 24 。这样就没问题了。其存储示意图如图 2所示。掌握了这两个原则,就能够分析所有数据存储对齐问题了。再来看几个例子, 应用以上两个原则来判断。例三: struct X{ double a; char b; intc; }S3; 首先根据原则一来分析。按照定义的顺序,先存储 double 型的 a,存储在第 0~7 个字节;其次是 char 型的 b,存储在第 8个字节;接下来是 int型的 c,顺序检查后发现前面三个四字节模块都被占用,因此存储在第 4个四字节模块,也就是第 12~15 字节。按照第一原则分析得到 16 个字节, 16 正好是最宽元素 a 的宽度 8的整数倍,因此结构体变量 S3 所占存储空间就是 16 个字节。存储结构如图 3所示。例四: struct X{ double a; char b; intc; char d; }S4; 仍然首先按照第一原则分析,得到的字节数为 8+4+4+1=17 ;再按照第二原则补齐,则结构体变量 S4 所占存储空间为 24 。存储结构如图 4所示: 例五: struct X{ double a; char b; intc; char d; int e; }S5; 同样结合原则一和原则二分析,可知在 S4 的基础上在结构体内部变量定义最后加入一个 int型变量后,结构体所占空间并未增加,仍为 24 。存储结构示意图如图 5所示。例六: 如果将例五中加入的变量 e放到第一个定义的位置,则情况就不同了。结构体所占存储空间会变为 32 。其存储结构示意图如图 6所示。 struct X{ int e; double a; char b; intc; char d; }S6; 补充:前面所介绍的都是元素为基本数据类型的结构体,那么含有指针、数组或是其它结构体变量或联合体变量时该如何呢? 。只要记住指针本身所占的存储空间是 4个字节就行了,而不必看它是指向什么类型的指针。例七: struct X struct Y struct Z {{{ char *a; int *b; double *c; }; }; }; 经测试,可知 sizeof(X) 、 si