您的位置:首页 > 其它

使用sizeof计算类对象所占空间大小

2013-04-20 15:19 357 查看
第一段代码:

#include <iostream>
using namespace std;

class s{
char c1;

char c2;
int a;
};

int main(){
cout<<"sizeof(s):"<<sizeof(s)<<endl;
system("pause");
return 0;
}


第二段代码

#include <iostream>
using namespace std;

class s{
char c1;
int a;
char c2;

};

int main(){
cout<<"sizeof(s):"<<sizeof(s)<<endl;
system("pause");
return 0;
}


这两段程序看似结果是一样的,都是sizeof(s):6,但是其实是错的,第一段的结果是sizeof(s):8,第二段的结果是sizeof(s):12。

现在让我们来分析一下:

这里涉及到了字节对齐这个概念,对齐跟数据在内存中的位置有关,如果一个变量的地址正好位于它长度的整数倍,他就被称作自然对齐。比如在32位cpu下,假设一个整型变量从地址0x00000004开始存储,那它就是自然对齐的。为什么是这样的呢?因为我们知道32位cpu每次是一下子取32bit的数据的,也就是4byte,也就是说一开始0x00000000,0x00000001,0x00000002,0x00000003这四个地址里的数据一下子就被cpu读取了,下面0x00000004~0x00000007正好存储的就是int型的数据(int型数据不是占4字节吗?啊,这里我说的是一般情况下的int型,有些系统int型不是占4字节的),所以要取这个int型的时候也是一下子就取走了。

但是如果这个int型变量开始的地址不是0x00000004,而是0x00000005,那么,就会有一个byte的部分存储到了0x00000008这个地址里去了,而这一个byte可就得等到cpu的下次取数时才能取出来了,也就是说要取完整这个int型数据,我们得取两次,而且还得把两次取出来的结果拼起来,还原成一个完整的int,这不就浪费时间了吗。所以编译器就会为了节省时间进行字节对齐,但是这是一种以空间换时间的方法,这也就造成了上面的结果。

下面让我们看看字节对齐的四个重要的基本概念:

1.数据类型自身的对齐值:

对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。

2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。

3.指定对齐值:#pragma pack (value)时的指定对齐值value。

4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。

现在终于回到正题了,为什么会出现那种结果呢?以第一个为例,先是向内存中存放一个char,占用了1个字节,再存放一个char,又是1个字节,现在来了一个int,如果紧跟着前面的char,就会有2byte到下一个取数周期里去了,之后还得再把它们拼起来,好麻烦啊。所以编译器就不管现在这个取数周期里剩下的两个空余的存储空间(开玩笑的,编译器怎么会不管它们呢,编译器会把两个填充字放进去),直接把int放到下面的取数周期里去了。这样,整个结构体就占了4字节的空间了。
那么第二个为何又不一样了呢,因为申请存储空间的顺序变了呀,先是一个char,再来的是一个int,最后才是一个char。

如果还是不懂呢,请移步/article/2647720.html,这位大牛讲得更全面详细,最关键的是最后有一副图。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: