麒王妃在使用sizeof()计算结构体和class大小的时候,往往很多时候计算出来并不是我们想要的结果。最近在使用的时候就特别想了解它内在的原理,搞懂它的本质。
很多人回答可能是5个字节。分析结构体的组成是:char占1个字,int占4个字节。1+4=5,没错吧?
既然它不是简单的把成员大小简单累加,想必它肯定是有一套规则,那是什么规则呢?那就是内存对齐
我的理解是按照一定的规则把它的位置排好,排列得有规有矩,方便计算机读取。
为了性能。为什么内存对齐为提高性能呢?举个例子,例如把4个字节从地址1写入到寄存器中。首先从前4个字节中读取3个节字,再从后面4个字节中读了1个字,最后放在寄存器中合并在一齐。读取一个数据到寄存器中消耗了这么多步骤,对于CPU性能来说是挺大的负担。如果是字节对齐了,从0开始连续读取4个字,寄存器刚好也是4个字节,只需要一次读写即可,大大提高了读取效率。
想想我们平时要把物品整理对齐的时候,一般都有参照物或对齐的标准。如果把箱子排好,是一个个紧密对齐排列呢,还是间隔排列呢,这个标准会影响排列后使用的空间。
对于内存对齐,同样也是有一个参考标准。编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式,n即为对齐的标准。
拿回箱子排列的例子来说,可能每一个箱子的大小不一样,有些是短一点,有些是长一点,可能排列的位置也有不一样。
第一个字段char,偏移量(offset)为0,占用空间1个字节,结束位置为1;
int的大小是4 bytes,字节对齐变量为16 bytes。比较两者间选择小的一个,此时4 bytes作为偏移参考量X。
从当前偏移量1开始,寻找偏移参考量X最小的倍数位置。4的倍数可以是:4,8,12,16等等,当前最小的为4。然而1,2,3的位置空了,需要填充,从第4个byte开始连续4个byte为int的空间。
画重点:char型占用空间为1 byte,则其起始位置必须可被1整除。int为4 bytes,其起始位置必须是可以被4整除。
内存对齐的过程如上,影响同一个结构体的内存布局的关键是:以多少字节来对齐,如上面所说的n。最开始的例子,实际上可以通过设置n为1,可以得到size为5。
|