使用sizeof计算类对象所占空间大小
2013-04-20 15:19
357 查看
第一段代码:
第二段代码
这两段程序看似结果是一样的,都是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,这位大牛讲得更全面详细,最关键的是最后有一副图。
#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,这位大牛讲得更全面详细,最关键的是最后有一副图。
相关文章推荐
- 使用sizeof计算虚继承的类对象的空间大小
- 使用sizeof计算虚拟继承的类对象的空间大小
- 使用计算总内存大小的方法确定jvm中为对象分配的存储空间大小
- cpp中使用sizeof和计算类占用空间的大小
- 使用 sizeof 计算类对象所占空间大小
- 使用sizeof计算普通变量所占空间大小
- JVM —— Java 对象占用空间大小计算
- oracle计算表要使用的空间的大小
- sizeof计算含有虚函数的类对象的大小
- 关于类对象大小的 sizeof 计算问题
- java对象的内存布局(一):计算java对象占用的内存空间以及java object layout工具的使用
- 不使用sizeof计算int的大小
- sizeof计算对象所占内存的大小详解
- 关于类对象大小的 sizeof 计算问题
- 关于类对象大小的 sizeof 计算问题(续)
- 创建表空间以及用户,授予权限,查看表空间名称及大小,物理文件的名称及大小,数据库的创建日期和归档方式,数据库的版本,数据库库对象,表空间的使用情况,表空间读写
- 使用sizeof计算类的大小
- 使用sizeof计算内存空间_第2篇
- sizeOf计算空间大小的总结
- 关于类对象大小的 sizeof 计算问题