关于sizeof的笔试面试题具体解释
原创Blog,转载请注明处处
http://blog.csdn.net/hello_hwc
注意:sizeof是编译期计算出结果的,这一点对后面的理解非常重要
一、关于结构体
先看下代码
#include "stdafx.h" #include <iostream> using namespace std; typedef struct { char a:3; char b:3; char c:3; char d:3; char e:3; }test1; typedef struct { char a:3; char b:4; char c:5; char d:6; char e:7; }test2; typedef struct { char a:1; char b:2; char c:3; char d:4; char e:5; }test3; typedef struct{ int a; char b; char d; long c; }test4; typedef struct{ int a; char b; long c; char d; }test5; int _tmain(int argc, _TCHAR* argv[]) { cout<<sizeof(test1)<<endl; cout<<sizeof(test2)<<endl; cout<<sizeof(test3)<<endl; cout<<sizeof(test4)<<endl; cout<<sizeof(test5)<<endl; return 0; }然后贴上执行结果
解释下为什么
1、对于test1,结果是3Byte。有些同学好奇,3bit*5 = 15bit。不是应该占用2Byte吗?但是计算机没你大脑智能。它管理bit的方式是8bit一组。所以对于一组8bit,仅仅能放下两个3bit,另外2bit没用。所以,对于test1来说。三个Byte是这么分配的。
1Byte(3bit,3bit,2bit填充)2Byte(3bit,3bit,2bit填充)3Byte(3bit,5bit填充)
2、对于test2结果是4Byte.有了test1的解释,这里不难理解了吧。我再解释下内存分配。
1Byte(3bit,4bit,1bit填充)2Byte(5bit,3bit填充)3Byte(6bit,2bit填充)4Byte(7bit,1bit填充)
3、test3结果是3Byte。和上述两个类似
4、test4的结果是12。为什么不是4+1+1+4呢?(我这里long是4Byte),由于C++对于Byte的管理仍然要内存对齐。我这里的内存对其是4Byte。所以。内存占用是这种4Byte(Int)4Byte(char,char,2Byte填充)4Byte(long)
5、有些同学会好奇。为什么两个结构体声明换了个顺序,差了4Byte。
相同是由于内存对齐
二、字符串与char*和char数组
// testforyou.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <string> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { string s = "hellohwc"; char * s1 = "hellohwc"; char s2[] = "hellohwc"; char s3[100]; char* s4=(char*)malloc(100); void *s5=(void*)malloc(100); cout<<sizeof(s)<<endl; cout<<sizeof(s1)<<endl; cout<<sizeof(s2)<<endl; cout<<sizeof(s3)<<endl; cout<<sizeof(s4)<<endl; cout<<sizeof(s5)<<endl; return 0; }执行结果
解释下
对于String类型。每一个编译器给分配内存的空间都是一定的。我这里是32Byte。
所以,无论字符串长度多长,内存分配都是32。当然也有4,16等情况,因编译期不同而不同。
1、char * s1,s1本身是个指针,所以长度是4个字节,跟后面指向什么没关系。
2、s2是数组保存了一个字符串。因为字符串最后一个隐藏的结束符。
所以,长度为8+1 = 9
3、s3是数组。在编译期分配了100*1 = 100Byte,所以结果是100
4、s4和s5都是指针,长度4Byte。
三、类
先看代码
// testforyou.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <string> using namespace std; class emptyClass1{ public: emptyClass1(){} ~emptyClass1(){} }; class emptyClass2{ public: emptyClass2(){} virtual ~emptyClass2(){} }; class hwcBase{ public: hwcBase(){} virtual ~hwcBase(){} private: int base; }; class hwcSubFirst:hwcBase{ public: hwcSubFirst():hwcBase(){} ~hwcSubFirst(){} private: int sub; }; class hwcSubSecond:hwcBase{ public: hwcSubSecond():hwcBase(){} ~hwcSubSecond(){} private: int sub; char sub2; }; int _tmain(int argc, _TCHAR* argv[]) { cout<<sizeof(emptyClass1)<<endl; cout<<sizeof(emptyClass2)<<endl; cout<<sizeof(hwcBase)<<endl; cout<<sizeof(hwcSubFirst)<<endl; cout<<sizeof(hwcSubSecond)<<endl; return 0; }
执行结果
解释下:
1、对于一个空的类。在内存中要存在一个标示来区分,所以即使是空的。也要分配一个字节
2、相同是empty的类,可是有一个虚的析构函数,所以,保存了一个指针(vptr)指向虚表。
一个指针4Byte
3、hwcBase类,有一个Int占用4Byte,一个指针(vptr)。所以共占用8Byte
3、hwcSubFirst,继承来一个Int,本身有一个Int。加上一个vptr指针,共12字节
4、hwcSubSecond,和hwcSubFirst类似,可是多了一个char,考虑到内存对其。12+4 = 16字节