在没有#pragma pack宏的情况下,内存对齐的规则如下:
规则1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。
规则2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
规则3:收尾工作,结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍.不足的要补齐.
规则1示例:
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { struct A{ int *a; short b; int c; char d; float e; double f; }; struct A a; printf("0x%x [0,1,2,3] ",&a.a); printf("0x%x [4,5] ",&a.b); printf("0x%x [8,9,10,11] 规则1 ",&a.c); printf("0x%x [12] ",&a.d); printf("0x%x [16,17,18,19] 规则1 ",&a.e); printf("0x%x [24,25,26,27,28,29,30,31] ",&a.f); printf("%d ",sizeof(struct A)); return 0; }
规则2示例:
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { struct B{ char a; int b; }; struct A{ int *a; short b; struct B b1; int c; char d; float e; double f; }; struct A a; printf("0x%x [0,1,2,3] ",&a.a); printf("0x%x [4,5] ",&a.b); printf("0x%x [8] 规则2 ",&a.b1.a); printf("0x%x [12,13,14,15] ",&a.b1.b); printf("0x%x [16,17,18,19] 规则1 ",&a.c); printf("0x%x [20] ",&a.d); printf("0x%x [24,25,26,27] 规则1 ",&a.e); printf("0x%x [32,33,34,35,36,37,38,39] ",&a.f); printf("%d ",sizeof(struct A)); return 0; }
规则3示例:
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { struct A{ short a; double b; }; struct A a; printf("0x%x [0,1] ",&a.a); printf("0x%x [8,9,10,11,12,13,14,15] 规则1 ",&a.b); printf("%d 规则3 ",sizeof(struct A)); return 0; }
使用#pragam pack(n)更改编译默认的对齐方式:
规则4:告诉编译器,所有的对齐按照min(n,当前成员的大小)的整数倍进行对齐。
规则5:收尾工作,结构体的总大小,也就是sizeof的结果,必须是min(n,其内部最大成员的大小)的整数倍.不足的要补齐.
#include <stdio.h> #include <stdlib.h> #pragma pack(4) int main(int argc, char *argv[]) { struct A{ short a; short b; double c; }; struct A a; printf("0x%x [0,1] ",&a.a); printf("0x%x [2,3] 规则4 ",&a.b); printf("0x%x [4,5,6,7,8,9,10,11] 规则4 ",&a.c); printf("%d 规则5 ",sizeof(struct A)); return 0; }
参考:http://blog.csdn.net/hairetz/article/details/4084088