2.性能原因:数据结构(尤其是栈)应该尽可能在自然边界上对齐,原因在于,为了访问未对齐的内存,处理器需要作两次内存访问,而对齐的内存访问仅需要一次访问。
规则:
数据成员对齐规则:结构(struct)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
结构(struct)的整体对齐规则:自数据成员完成各自对齐后,结构本身也要对齐,对齐将按照#pragma pack指定的数值和结构最大数据成员长度中,比较小的那个进行
结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储
假设CPU要读取一个4字节大小的数据到寄存器中(假设内存读取粒度是4)
1.数据从0字节开始(内存对齐)
2.数据从1开始(内存不对齐)
当数据从0字节开始的时候,直接将0-3四个字节完全读取到寄存器,结算完成
当数据从1开始的时候,问题很复杂,首先将前4个字节读到寄存器,再次读取4-7字节的数据进寄存器,接着把0字节,567字节的数据剔除,最后合并1234字节的数据进寄存器,对一个内存未对齐的寄存器进行了这么多额外 *** 作,大大降低了CPU的性能。
这还属于乐观情况(性能原因),还有平台的移植原因,因为只有部分CPU肯干,其他部分CPU遇到未对齐边界就直接罢工了
字节对齐:
1.第一个成员在与结构体变量偏移量(offset)为0的地址处。
2.其他成员变量要对齐到对齐数的整数倍的地址处
(1)对齐数=对齐系数与该成员大小的较小值。
(2)如果有宏定义 #pragma pack(n)则它中的n 就是对齐系数。
(3)VS中默认的对齐系数为8,linux中的默认为4.
3.结构体总大小为最大对齐数(每个成员变量除了第一个都有对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,
结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
16的话,大概是因为lz的gcc默认是64位的编译吧,如果是64位的话,可以看一下int的字节数,应该是8吧,那当然是以8为模了我的是32位的,所以对齐模数默认是4,12没有问题
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)