深刻理解类的填充规则

  struct/class中的成员变量所占总大小不是简单地将各个成员变量的大小相加,而是要考虑到读取效率,有时须要添加填充字节。
  好比有些平台每次读都是从偶地址开始,若是一个int型(假设为32位系统)若是存放在偶地址开始的地方,那 么一个读周期就能够读出这32bit,而若是存放在奇地址开始的地方,就须要2个读周期,并对两次读出的结果的高低字节进行拼凑才能获得该32bit数据。


  填充规则: (1)结构体变量的首地址可以被其最宽基本类型成员的大小所整除;
        (2)结构体每一个成员相对于结构体首地址的偏移量都是成员大小的整数倍,若有须要编译器会在成员之间加上填充字节
        (3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,若有须要编译器会在最末一个成员以后加上填充字节。


  判断一个类的大小一般用到规则(2)和(3)。
例子1:基本分析
spa

class Coo {
    char c;
    short s;
    int i;
    short s2;
};

首先c的偏移量是0,而0是1的整数倍,所以不用加填充;s的偏移量是1,而1不是2的整数倍,所以要填充1;
i的偏移量是4,而4是4的整数倍,所以不用填充;s2的偏移量是8,而8是2的整数倍,所以不用填充。
最后,在类coo中,最宽基本类型是int,大小是4,而目前咱们的类大小为: 1 (+1) + 2 + 4 + 2 = 10,不是4的整数倍,所以要在最后填充2。


例子2:空类
code

class Coo {};

空类的大小是1。若是coo的大小是0,就没法区别其余的空类了。


例子3:有静态成员
blog

class Coo {
    static int i;
};

类的大小是1。静态数据成员不属于实例的一部分,而是放到了全局数据区。


例子4:类嵌套
ci

class CooIn {
    int i;
    short s;
    int i2;
};

class Coo{
    char c;
    CooIn ci;
    double d;
};

首先分析被嵌套的CooIn的大小,易得为12,且最宽数据成员大小为4。而后以ci为分界点,前面的大小要为4的整数倍,所以为1 + 3,然后面
的分析就没有什么特殊性了。注意,不能把CooIn在Coo内展开为
编译器

class Coo{
    char c;
    int i;
    short s;
    int i2;
    double d;
};

要将CooIn看做一个总体,其传输单位为4,所以ci前在加上CooIn时,要保证是4的整数倍    it

相关文章
相关标签/搜索