原文:http://blog.sina.com.cn/s/blog_7c983ca60100yfdv.html#SinaEditor_Temp_FontName

(1)      sizeof是操作符,不是函数。

MSDN:The sizeof keyword gives the amount of storage, in bytes, associate with a variable or a type(including aggregate types). This keyword returns a value of type size_t(typedef unsigned int size_t).

语法:sizeof(object);=> sizeof(1);   sizeof(typename);=>sizeof(int);  sizeof object;=>sizeof 1;(注意sizeof typename是错误的)

(2)      sizeof不能求得void类型的长度。

你不能用sizeof(void);这样将产生:error C2070: illegal sizeof operand

比如如下代码:

void fun(){

}

int main(){

cout<<sizeof(fun())<<endl;

return 0;

}//这个编译是不会通过的

char fun(){

return ‘a’;

}

int main()

{

cout<<sizeof(fun())<<endl;

return 0;

}//引申一下,这个是测量返回值的长度,因此是1,而不是指针的长度4.结合第八点来看。

(3)      sizeof能求得void类型的指针的长度。

目前基本上所有的编译器都把指针的大小看做是4byte。其实指针也是变量,只不过这个变量很特殊,它是存放其他变量的地址的变量。又由于目前32位计算机平台上的程序段的寻址范围是4GB,寻址的最小单元是Byte,4GB等于232byte。这么多得内存起地址如何编码,只需要用32个bit就行了,而32bit=32、8=4Byte,也就是说只要4Byte就能存储这些内存的地址了。因此对任何类型的指针变量进行sizeof运算其结果就是4.(一个疑问,指针类型用4Byte只存储了指针指向的地址,如何区分是何种类型的指针呢?

(4)      sizeof能求得静态分配的内存的数组的长度。

int a[10];sizeof(a); 这样可求得长度是10*4=40.(引申问题:数组名和指针的区别。参看下篇),另外注意char ch[]=”abc”; sizeof(ch);结果为4,注意字符串数组末尾有’\0’,通常我们可以利用sizeof来计算数组中包含的元素个数。其做法是:int n=sizeof(a)/sizeof(a[0]);

要注意对函数的形参数组使用sizeof的情况。如:

void fun(int arr[10]){

int n = sizeof(arr);

}//n的值为4

这里的原因是在函数参数传递时,数组被转化成指针了。加入直接传递整个数组的话,那么必然涉及到数组元素的拷贝(实参到形参的拷贝),当数组非常大时,这会导致执行效率极低!而只传递数组的地址(即指针)那么只需要拷贝4Byte。

引申:sizeofstrlen的区别:

strlen(char*)函数求的是字符串的实际长度,它求的方法是从开始遇到第一个’\0’,如果你只定义没有给它赋初值,这个结果是不定的,它从指针指向的首地址一直找下去,直到遇到’\0’为止。

char aa[10];strlen(aa);          //结果是不定的   sizeof(aa);      //结果是10

char aa[10]={‘\0’};strlen(aa);  //结果为0         sizeof(aa);      //结果是10

char aa[]=”LRP”;strlen(aa);     //结果为3             sizeof(aa);      //结果是4

char*aa=”0123456789”;   //字符串常量的情况

sizeof(aa);        //结果为4,指针的长度

sizeof(*aa);       //结果为1,第一个字符的空间

strlen(aa);         //结果为0,该字符串的长度

char aaa[]={"LRPLRP"};

int a,b;

fun(aaa,a,b);

void fun(char aaa[],int&a,int&b)

{

a=strlen(aaa);

b=sizeof(aaa);

}

//得到的a=6,b=4.在函数内部,虽然aaa转化成指针,但是strlen还是测试aaa开始直到’\0’为止的字符串的长度,而sizeof则是测指针的长度。

(5)      sizeof不能求得动态分配的内存的大小

例如int*a = new int[10]; int n = sizeof(a); 得到n的值是4。

(6)      sizeof不能对不完成的数组求长度

假设有两个源文件:file1.cpp和file2.cpp,其中file1.cpp定义:

int arrayA[10]={1,2,3,4,5,6,7,8,9,10};

int arrayB[10]={11,12,13,14,15,16,17,18,19,20};

file2.cpp中包含如下几个语句:extern arrayA[]; extern arrayB[10];

cout<<sizeof(arrayA)<<endl;   //编译出错

cout<<sizeof(arrayB)<<endl;

在file1.cpp中第三条语句编译出错,而第四条语句正确。原因:sizeof(arrayA)试图求不完整数组的大小。这里的不完整的数组是指数组大小没有确定的数组。sizeof运算符的功能是求某种对象的大小,然而声明:extern int arrayA[]只是告诉编译器arrayA是一个整型数组,但是并没有告诉编译器它包含多少个元素,因此对file2.cpp中得sizeof来说它无法求出arrayA的大小,所以编译器干脆不让你编译通过。arrayB明确告诉了arrayB是一个包含10个元素的整型数组,因此大小事确定的。

(7)       当表达式作为sizeof的操作数时,它返回表达式的计算类型大小,但是它不对表达式求值。(这点很重要)

char ch=1;

int num=1;

int n1=sizeof(ch+num);           //结果n1=4

int n2=sizeof(ch=ch+num);     //n2=1,ch=1

由于默认类型转换原因,ch+num的计算结果的类型是int,因此n1的值为4.而表达式ch=ch+num的结果的类型是char,记住虽然在计算ch+num时,结果为int,但是把结果赋值给ch时又进行了类型转换,因此表达式的最终类型还是char,因此n2等于1。

对于n2=sizeof(ch=ch+num); 乍一看改程序貌似实现了让ch加上num并赋值给ch的功能,事实并非如此,由于sizeof只关心类型大小,所以它自然不应该对表达式求值。但是,int len=3; cout<<sizeof(int[++len])<<”,”<<len;输出地答案却是16,4.(原文中作者说得时在Dev C++编译器下,但是经过在VC下测试,编译不通过。后来改成int num = 3;      int aaa[]={1,2,3,4,5,6}; cout<<sizeof(aaa[++num])<<","<<num<<endl;输出结果却是4,3.由此可见++num操作并未执行),因此尽量不要在sizeof中直接对表达式求大小,以免出现错误。

(8)      sizeof可以对函数调用求大小,并且求得的大小等于函数返回类型的大小,但是不执行函数体。

int fun(int &num)

{

int a,b;

a = 10;

b = 2;

num = a/b;

return num;

}

int main()

{

int num = 0;

cout<<sizeof(fun(num))<<endl;

cout<<num<<endl;

return 0;

}//输出结果4 0

sizeof(fun(num))得到的是函数返回类型的大小,而fun(num)的返回值类型是int,所以等价于sizeof(int)得到结果为4.另外不要认为这个长度为fun函数内部的局部变量所占空间的大小(认为结果为8,即a和b两个int的长度也是错误的)另外也注意,sizeof(fun(num))也不是求函数指针的大小,切记是求得返回值类型的长度大小

这里跟特征7很类似。sizeof的操作对象是函数调用时,它不执行函数体。为此,建议大家不要把函数体放在sizeof后面的括号里,这样让人误以为函数体执行了,其实它根本没执行。另外可知:不能对返回类型是void的函数使用sizeof求其大小,如2中讲得编译报错。

另外注意sizeof(fun)的大小是多少呢?其实得不到答案,原因是编译不通过。(很多人可能认为fun是函数名,而再把函数名等价于函数的地址,地址是指针),于是得到了其值是4.但是事实却不是这样,却是编译不通过。

(9)      sizeof求得结构体(及其对象)的大小并不等于各个数据成员对象的大小之和

结构体的大小跟结构体成员对其有密切关系,而并非简单地各个成员的大小之和。比如两个结构体AA和BB。,使用sizeof分别得出结果是24和16.可以看出sizeof(AA)并不等于sizeof(int)+sizeof(double)+sizeof(int)

struct AA{

int aa;

double bb;

int cc;

};

struct BB{

int aa;

int bb;

double cc;

};

结构体成员对齐的规则:(1)结构体大小等于结构体内最大成员大小的整数倍;(2)结构体内的成员的首地址相对于结构体首地址的偏移量是其类型大小的整数倍,比如说double型成员相对于结构体的首地址的偏移量应该是8的整数倍;(3)为了满足规则1和规则2编译器会再结构体成员之后进行字节填充。

在进行设计时,组号仔细安排结构体中各个成员的顺序。

(10)  sizeof不能用于求结构体的位域成员的大小,但是可以求得包含位域成员的结构体的大小。

位域:类型的大小都是以字节(byte)为基本单位的,比如sizeof(char)为1byte。但是bool类型取值只有true和false,按理只用1bit就够了,但事实上sizeof(bool)等于1.为了提供一种能对变量的存储空间进行精打细算的机制,这就是位域。简单来说在结构体成员变量后面跟上的一个冒号+一个整数,就代表位域,请仔细看以下结构体:

struct A{

bool b:1;

char ch1:4;

char ch2:4;

}item;

该结构体试图让bool类型的变量b只占用1个bit,让ch1和ch2分别只占用4个bit,以此来达到对内存精打细算的功能。语句sizeof(item.b)和sizeof(item.ch1)等对位域成员求大小的语句均不能通过编译。其原因:sizeof以byte为单位返回操作数的大小。

对包含位域的结构体可以使用sizeof求其大小,但其求值规则比较复杂,不涉及到成员对齐,还与集体编译环境有关。

延伸:class A{};sizeof(A)的结果为1,其原因:类的实例化是在类内存中分配一块地址,每个实例在内存中得都有独一无二的地址,同样空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以其长度为1。(编译器为了区分不同的类,在类中加了一个char类型,另外,如果一个文件中有256个空类,即大于char类型表示的范围,就不能区分空类了)

C++面试中关于sizeof问题总结的更多相关文章

  1. 面试中有关C++的若干问题

    面试中有关C++的若干问题 By 晴天, 2014.5.16晚 什么是多态?简要说一下C++中的多态的概念. (1)定义:多态是指相同对象收到不同消息或者不同对象收到相同消息产生不同的行为. (2)C ...

  2. 在面试中忽然发现DateTime的一些...

    今天说说我面试中碰到的一个小问题,在我问起DateTime为什么无法赋值NULL值,一般第一反应都认为它是值类型,不是引用类型,但随后我查阅了度娘自我学习到它是结构类型,那么随之而然就无法赋值NULL ...

  3. 聊聊 C 语言中的 sizeof 运算

    聊聊 sizeof 运算 在这两次的课上,同学们已经学到了数组了.下面几节课,应该就会学习到指针.这个速度的确是很快的. 对于同学们来说,暂时应该也有些概念理解起来可能会比较的吃力. 先说一个概念叫内 ...

  4. 面试中关于Java你所需知道的的一切

    本篇文章会对面试中常遇到的Java技术点进行全面深入的总结,帮助我们在面试中更加得心应手,不参加面试的同学也能够借此机会梳理一下自己的知识体系,进行查漏补缺. 1. Java中的原始数据类型都有哪些, ...

  5. 前端js面试中的常见的算法问题

    虽说我们很多时候前端很少有机会接触到算法.大多都交互性的操作,然而从各大公司面试来看,算法依旧是考察的一方面.实际上学习数据结构与算法对于工程师去理解和分析问题都是有帮助的.如果将来当我们面对较为复杂 ...

  6. JAVA面试中问及HIBERNATE与 MYBATIS的对比,在这里做一下总结

    我是一名java开发人员,hibernate以及mybatis都有过学习,在java面试中也被提及问道过,在项目实践中也应用过,现在对hibernate和mybatis做一下对比,便于大家更好的理解和 ...

  7. memset中的sizeof

    记录memset中的sizeof的用法, unsigned char *buff = (unsigned char*) malloc(128 * sizeof(char)); //错误的:memset ...

  8. 谈谈如何在面试中发掘程序猿的核心竞争力zz

    早两天看了知乎日报的这篇文章<什么是程序员的核心竞争力?>,caoz讲的几点是让我感同身受.这让我联想起了给程序猿的面试,其实也就是通过短暂的接触来发掘程序猿的核心竞争力.接下来我就谈谈我 ...

  9. java面试中的智力题

    智力题,每个正式的笔试.面试都会出,而且在面大企业的时候必然会问到,笔者曾在很多面试中,都被问到过,不过答得都不是很好,因为时间很短,加上我们有时候过于紧张,所以做出这类问题,还是有一定的难度,从这篇 ...

随机推荐

  1. openfire 连接sqlserver 2008 的一个问题

    由于本人的笨拙,搞了一天才终于搞好,说实在的问题归根结底还是在sql上,要相信openfire是没问题的.好了,不瞎扯了,说正题. 本人的机器环境为:win7.sqlserver 2008.jdk1. ...

  2. Dictionary和Hashtable的一些异同

    Dictionary和Hashtable 区别: Dictionary和Hashtable 区别 Dictionary Hashtable  支持范型 不支持 需要自己做线程同步 通过调用 Synch ...

  3. VC++ error C2248: “CObject::CObject”: 无法访问 private 成员(在“CObject”类中声明)

    在使用诸如:CArray或是 CList等类时,经常会出现此错误 此错误的原因是由于自定义的类的数组项时 有一个操作如  Add()  在这个操作中,实际上需要一个 = 操作,但是这个 =操作在 自定 ...

  4. RabbitMQ on windows开启远程访问

    我的RabbitMQ安装位置是:C:\Program Files (x86)\RabbitMQ Server\rabbitmq_server-3.5.6 为rabbitmq添加用户 C:\Progra ...

  5. Office 365 系列五 -------- Imap邮箱迁移步骤

    当客户购买了我们的Office 365之后,第一个功能必然是会用我们的企业邮箱,如果企业之前是用 263.腾讯.网易等的邮件厂商的话,必然会涉及到邮件的迁移, 其实说到邮箱迁移,我们办法很多,如果人数 ...

  6. redis 扩展 安装 和 memcached 安装

    在Windows下为PHP5.6安装redis扩展和memcached扩展   一.php安装redis扩展   1.使用phpinfo()函数查看PHP的版本信息,这会决定扩展文件版本       ...

  7. mosquitto_pub和mosquitto_sub 命令参数说明

    mosquitto_pub 命令参数说明 1. -d  打印debug信息 2. -f  将指定文件的内容作为发送消息的内容 3. -h  指定要连接的域名  默认为localhost 4. -i   ...

  8. error-2016-2-15

    错误:该请求包含双重转义序列,而 Web 服务器上配置的请求筛选拒绝双重转义序列原因:一些URL中可能会包含+号等符号,然后IIS7以上的版本会默认拒绝请求此URL,需要进行如下的修改. 解决PHP中 ...

  9. centos rar安装

    wget http://www.rarsoft.com/rar/rarlinux-x64-5.1.1.tar.gz tar -zxvf rarlinux-x64-5.1.1.tar.gz # cd r ...

  10. Scala包

    #引入包的全部成员的办法 import scala.collection._ #引入同一个包中的几个成员 import scala.collection.{A,B} #重名 要 重命名 import ...