分享

C 结构体可以继承!struct/class等内存字节对齐问题详解

 昵称11935121 2018-08-16

问题引入

C++结构体可以继承!struct/class等内存字节对齐问题详解

如下结构体:

C++结构体可以继承!struct/class等内存字节对齐问题详解

更多C/C++学习资料,请私信我“代码”,即可获取

那么一个这样的结构体变量占多大内存呢?也就是:cout<><>会输出什么?在了解字节对齐方式之前想当然的会以为:

sizeof(Stu) = sizeof(int)+sizeof(char)+sizeof(float) = 9.

然而事实并非如此!

字节对齐原则

在系统默认的对齐方式下:每个成员相对于这个结构体变量地址的偏移量正好是该成员类型所占字节的整数倍,且最终占用字节数为成员类型中最大占用字节数的整数倍

在这个例子中,id的偏移量为0(0=4*0),sex的偏移量为4(4=1*4),hight的偏移量为8(8=2*4),此时占用12字节,也同时满足12=3*4.所以sizeof(Stu)=12.

出现继承关系时

C++结构体可以继承!struct/class等内存字节对齐问题详解

更多C/C++学习资料,请私信我“代码”,即可获取

基类的成员总是在派生类的前面。而且即使有字节对齐,基类对齐后派生类的成员不会占用基类填充的字节,即计算好基类所占字节数后,这些字节只能由基类拥有,不能被派生类的成员占用(即char b后面有3字节的填充,之后才有char c)在派生类中成员的分布只需满足每个变量起始字节序号为该类型所占字节数的整数倍且最终大小为占用字节数最大的类型对应的字节数的整数倍。排列如下:

C++结构体可以继承!struct/class等内存字节对齐问题详解

更多C/C++学习资料,请私信我“代码”,即可获取

关联关系

必须满足:

1.结构体/类与结构体/类之间不会共用自动补齐的内存,即一个结构体变量/对象对齐之后填补的内存不允许被其他变量/对象占用;

2.结构体的起始字节位置必须是该结构体中所占字节数最大的变量的字节数的整数倍;

3.最终所占字节数必须是最大所占字节数最大的变量的字节数的整数倍。

强制对齐

当然,有时候考虑到其他特殊用途,使用#pragma pack(n)来设定以n字节对齐的方式(n可取2的较小次幂,即1,2,4,8,具体取值范围以及默认值与所使用的编译器有关。笔者所测试的环境下vs/vc默认为8,gcc默认为4)。

n字节对齐就是说变量存放的起始地址的偏移量有两种情况:

  • 如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式;

  • 如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。

结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。比如有以下代码:

C++结构体可以继承!struct/class等内存字节对齐问题详解

更多C/C++学习资料,请私信我“代码”,即可获取

这时候编译器就会被迫使用我们约定的字节对齐方式,即4字节对齐,因此c1占4字节,d占8字节,i占4字节,c2占4字节,共20字节;

如果我们没有设置字节对齐方式,仍然使用默认对齐的话,这里sizeof(Test) = 24。

C++类对齐原则

C++结构体可以继承!struct/class等内存字节对齐问题详解

更多C/C++学习资料,请私信我“代码”,即可获取

  • 在不考虑(或者说在没有)虚函数和虚继承的情况下,sizeof(自定义类)也按照类似上面的方式来计算。

  • 如果一个类拥有虚函数或者虚继承,则在数据成员的基础上相当于多一个指针类型的数据成员(位置在所有数据成员的前面),最后计算时加上即可。

  • 如果一个类或者结构体不含有任何数据成员,且无虚函数以及虚继承,则sizeof()结果为1。

  • 静态成员不在计算范围。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多