写出一个struct,而后sizeof,你会不会常常对结果感到奇怪?sizeof的结果每每都比你声明的变量总长度要大,这是怎么回事呢?讲讲字节对齐吧.数组
若是体系结构是不对齐的,A中的成员将会一个挨一个存储,从而sizeof(a)为11。显然对齐更浪费了空间。那么为何要使用对齐呢?
体系结构的对齐和不对齐,是在时间和空间上的一个权衡。对齐节省了时间。假设一个体系结构的字长为w,那么它同时就假设了在这种体系结构上对宽度为w的数据的处理最频繁也是最重要的。它的设计也是从优先提升对w位数据操做的效率来考虑的。好比说读写时.............此处省略50万字bash
上面是你随便 google一下,人家就能够跟你解释的,一大堆的道理,咱们没怎么多时间,讨论为什么要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记如下3条原则:(在没有#pragma pack宏的状况下,务必看完最后一行)测试
1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,之后每一个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,好比说是数组,结构体等)的整数倍开始(好比int在32位机为4字节,则要从4的整数倍地址开始存储)。google
2:结构体做为成员:若是一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)设计
3:收尾工做:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.code
typedef struct bb { int id; //[0]....[3] double weight; //[8].....[15] 原则1 float height; //[16]..[19],总长要为8的整数倍,补齐[20]...[23] 原则3 }BB; typedef struct aa { char name[2]; //[0],[1] int id; //[4]...[7] 原则1 double score; //[8]....[15] short grade; //[16],[17] BB b; //[24]......[47] 原则2 }AA; int main() { AA a; cout<<sizeof(a)<<" "<<sizeof(BB)<<endl; return 0; }
结果是内存
48 24
ok,上面的全看明白了,内存对齐基本过关.编译器
再讲讲#pragma pack().io
在代码前加一句#pragma pack(1),你会很高兴的发现,上面的代码输出为编译
32 16
bb是4+8+4=16,aa是2+4+8+2+16=32;
这不是理想中的没有内存对齐的世界吗.没错,#pragma pack(1),告诉编译器,全部的对齐都按照1的整数倍对齐,换句话说就是没有对齐规则.
明白了不?
那#pragma pack(2)的结果又是多少呢?对不起,5分钟到了,本身去测试吧.
Vc,Vs等编译器默认是#pragma pack(8),因此测试咱们的规则会正常;注意gcc默认是#pragma pack(4),而且gcc只支持1,2,4对齐。套用三原则里计算的对齐值是不能大于#pragma pack指定的n值。