码迷,mamicode.com
首页 > 其他好文 > 详细

关于sizeof的那些事

时间:2015-03-30 23:15:14      阅读:400      评论:0      收藏:0      [点我收藏+]

标签:

一 结构体

先上代码:

struct A {
  int a;
  double d;
  char b; 
  short c;
};

以上代码的sizeof(struct A)为24。分析:

a占用4字节,由于d占用8字节,且d需要在8字节处对齐,因此a不仅有4字节存放内容,并且占另外的4个字节使得d位于8字节处。由于c需要在2字节处对齐,所以b占用了2个字节,c占用两个字节,目前总共是20字节,但是整个结构体A根据最大字节对齐,因此为8字节对齐,为了使得类型位struct A的数组的下一个元素处于正确的对齐位置,此结构体还要额外占用4字节,总共是20+4=24字节。

内存分配见下图:(其中红颜色的为对齐需要的额外内存,黑颜色的为变量内容所占字节数)

技术分享

再来看看接下来的代码,比上面的代码多了一个 #pragma pack(4)

#pragma pack(4)
struct A {
  int a;
  double d;
  char b;  
  short c;
};
sizeof(struct A)为16。分析:

#pragma pack(4) 使得对齐方式为4字节对齐,因此对齐方式大于4字节的类型都要以4字节方式对齐,因此double也是以4字节方式对齐,struct A也是以4字节方式对齐。所以a只占用4字节,d占用接下来的8个字节,但是c是2字节对齐,比4要小,因此还是以2字节对齐方式对齐,所以b除了自己一个字节存储内容外,还要额外占用1个字节,使得c可以在2字节处对齐。此时struct A总共占4+8+2+2=16,而16是4的倍数,保证了struct A本身的对齐方式,因此结果为16。

内存分布图如下:

技术分享

总结:若没有规定对齐方式,则结构体内的元素按照所占用的字节数进行对齐,而结构体按照元素最大字节对齐方式对齐;

            若规定了对齐方式,例如规定4字节对齐,则对齐方式小于4字节的元素依然按照自身的对齐方式保持对齐,否则对齐方式大于4字节的元素按照4字节方式对齐。

基本类型的对齐方式(默认在32 bit环境下):bool-->1,char-->1,short-->2,int-->4,long-->4,long long-->8,float-->4,double-->8

二 类与类的继承

首先看看普通继承:

class Base {
public:
	virtual int init();
protected:
	int a;
	char b;
};

class Derived : public Base {
public:
	virtual int init();
protected:
	char b;
	int a;
};
在vs2010中得:sizeof(Base)=12,sizeof(Derived)=20。

分析:Base中含有虚函数,则有个虚指针vfptr_Base,占用4个字节,int占用4个字节,b占用一个自己,此时共有4+4+1=9个字节,而Base自身的对齐方式为4字节,因此最后补齐4的倍数为12字节。内存分配图如下:(c++标准规定虚函数表指针必须位于类实例的开头 参考于http://www.cppblog.com/xczhang/archive/2008/01/20/41508.html

技术分享

            Derived含有一个虚指针vfptr_derived,占用四个字节,然后含有Base中的int a和char b,其中Base::a占用四个字节,Base::b占用一个字节,此时Base完成,但需要补齐四字节(这里是根据vs2010中的Base::b和Derived::b的地址间距判断的,属于个人猜想,如有不对还望指教),此时占用字节数为4+4+4=12;接下来是Derived的成员变量了,其中Derived::b占用一个字节,而Derived::a需要在4字节处对齐,因此Derived::b之后有三个多余字节用于Derived::a的对齐使用,所以Derived的成员变量部分占用的字节数为1+3+4=8;因此Derived占用12+8=20个字节。内存分配如下:

技术分享

但是在g++环境下,sizeof(Derived)为16,而sizeof(Base)依然为12,通过观察Derived::Base::a,Derived::Base::b,Derived::b以及Derived::a的地址发现内存分布如下图:

技术分享

可见不同的编译器拥有不同的实现,因此要分清楚是哪个编译器。另外极力推荐这个博文,我个人认为非常有帮助http://www.cppblog.com/xczhang/archive/2008/01/20/41508.html

virtual继承和多重继承先不整理了,这个搞了我一天,我发现写博客还是比较累的,先休息休息。

关于sizeof的那些事

标签:

原文地址:http://blog.csdn.net/zhenxihongyan/article/details/44747811

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!