C,C++面试指南笔记_第1页
C,C++面试指南笔记_第2页
C,C++面试指南笔记_第3页
C,C++面试指南笔记_第4页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C语言语句是指以分号作为结束符,编译后产生机器指令的代码。预处理指令不是C语句。2、变量的声明和定义有什么区别?定义:为变量分配地址和存储空间。声明:不分配地址。ー个变量可以在多个地方声明,只能在ー个地方定义。加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。说明:很多时候ー个变量,只是声明,不分配内存空间,直到个体使用时オ初始化分配内存空间,如外部变量。3、以最简单的方式使电脑发出蜂鸣声音?使电脑发出蜂鸣有很多方法:可以调用beep:可以用汇编直接操作蜂鸣器对应的管脚。最简单的方式:#include"stdio.h''intmain(intargc,char*argv[])(printf(”\7");//常用字符的ASCI!值return0;}4、编程规范包括程序的可行性,可读性,可移植性及可测试性。可行性:是目的,也是规范的灵魂。通常要注意:预处理命令的使用;运算符优先级的区别;指针的使用等。可读性:变量和函数名的命名做到见名知义;适当加注释(写在代码的上方或右方);无参数函数时最好加void等。可移植性:使用标准库函数,并且把它们和ANSI/ISOC标准中定义的头文件放在ー起使用。等等。可测试性:增加打印消息,跟踪程序流程,这样可使测试者更加快捷地找到问题所在;嵌套最好不多于五层。等。5、变量与函数名命名的习惯满足命名规则,不能用关键字。(以下总结为可读性)标识符最好采用英文单词或其组合,切忌中英混用且不要过长。Windows系统中标识符通常大小写混排如LittleBoyo指针变量命名基本原则:一重指针为“p”+变量类型前缀+名称,如float类型指针pfStat.多重指针类似。程序中最好不要出现局部变量与全局变量完全相同的情况。符号常量常用下划线分隔单词。全局变量加前缀g_。类的数据成员加前缀m_(表示member),避免数据成员与成员函数参数同名时混。6、写出bool,int,float.指针变量(用flag表示的)与“零值”比较的if语句。•bool:if(flag) )else

B;)或:if(!flag)else((B;A;}不良习惯:)If(flag==TRUE);if(flag==FALSE);if(flag==l);if(flag==O)•int:If(O!=flag)或:If(O==flag)((A;B;})ElseElse({B;A;}}不良习惯:If(flag==FALSE);if(flag).•指针类型:If(NULL==flag)}Else(B;}或:if(NULL!=flag)(B;}Else(A;}不良习惯:If(p==O);if(p!=O);if(p).•float:constfloatNORM=0.0001;If((flag>=NORM)&&(flag<=NORM))(A;不良习惯:If(x==O.O);if(x!O.O).应当特别注意:在int,指针变量和零值比较时,把零值写在左边。是因为当把”=ゴ写成“=”时,编译器可以报错,否则这种逻辑错误不容易被发现。7、代码ー、shortsl=l;sl=sl+lL;代码二、shortsl=l;sl+=lL;以上两段代码是否都正确?类型转换关系:例如:short和int型数据相加,则将short转换成int.代码一中si是short,转换成long与1L相加,得到的是long和,但赋值给short型的si,所以不正确。改为:Shortsl=l;sl=(short)(sl+lL);代码二中“+=”会进行类型转换,所以正确。8、C中任何数据在内存中都是以二进制形式存放的。而数值是以补码表示的。字符型数据在内存中是按其ASCII码值来存储的,其ASCII码值在内存中也是以二进制形式存储的。9、什么是左值,什么是右值?左值位于赋值号左边,右值位于赋值号右边。常量不可寻址,变量可以,变量有两个相关值:地址值和数据值。数据值:存储在内存中的数据,也称为变量的右值。地址值:存储数据值的地址,也称为变量的左值。左值一般是变量,右值可以是变量,表达式或常量。即左值可以为右值,右值不可以为左值。10、字符型数据无论在!6位机上还是32位机上都是占ー个字节,而基本整型在16位机上占两个字节,在32位机上占四个字节。因此,用si沈of求字节数时要注意分情况。11、Sizeof与strlen的区别•sizeof是ー个操作符,而strlen是库函数。•Sizeof用来返回一个数据类型的占的字节数,参数可以是数据类型也可以是变量且后面的小括号可以不写。Strlen用来返回一个字符串的长度且只能以へ(T作为结束符的字符串为参数。•编译器在编译时就计算出sizeof的值,而strlen函数是在运行时オ计算出来。•数组做sizeof参数不退化,做strlen参数时退化为指针。例如:#include"stdio.h"#include"string.h"voidmain(void)charstr[10]=',abce";intx=strlen(str);inty=sizeof(str);printf("%d,%d\n",x,y);)结果为:4,1012、〃位域#include"stdio.h"structsi(inti:8;charj:4;inta:4;doubleb;);structs2(inti:8;intj:4;doubleb;inta:4;);structs3(inti;charj;doubleb;inta;);〃怎么区分是结构体还是位域??voidmain(void)(printf(',sizeof(sl)=%d\n',,sizeof(structsi));printf("sizeof(s2)=%d\n",sizeof(structs2));printf("sizeof(s3)=%d\n",sizeof(structs3));}注:在VC中都是24。怎么回事?书上是:16,24,32说每个数据都要对照结构体内最大数据字节数的最小公倍数补齐。位域:是把ー个字节中的位按照实际的需求分成不同的区域,表明每个区域位数,区域的域名,并允许程序按照域名进行操作。如此就可以把不同的对象用一个字节来表示。能节省空间。即成员均按二进制位分配。位域定义格式:struct位域的结构名{位域列表};位域列表表示形式:类型说明符位域名:位域的长度如上sl,s2,s3o几点说明:ー个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另ー个位域时,应从下ー单元起存放该位域。也可以有意使某位域从下ー单元开始。如:Structwy(Unsigneda:6;Unsigned:〇;//空域Unsignedb:4;//从下ー单元开始存放Unsignedc:4;);在这个位域定义中,a占第一个字节的6位,后2位填0表示不使用,b从第二字节开始,占用4位,c占用4位。由于位域不能跨两个字节,因此位域的长度不能大于一个字节的长度,也就是不能超过8位二进制位。位域可以无位域名,这时它只用来填充或调整位置。无名的位域是不能使用的。例如:structkyInta:l;Int:2;〃这两位不能使用Intb:3;Intc:2;);13、C和C++中的static有什么区别?C中:static用来修饰变量或函数,主要用来说明这个变量或函数只能在本文件代码块中访问,且static修饰的变量存放在段存储区。主要有以下用途:定义局部静态变量存储在静态存储区,在程序运行期间不会释放,只在声明时初始化ー次,若没有初始化,自动赋值为〇或空字符。具有局部变量的’’记忆性”及生存周期“全局性"特点。''记忆性”是指在两次函数调用时,第二次调用开始时,变量能够保持上一次调用结束时的值。''全局性”可改善函数返回指针的问题,局部变量的问题在于当函数退出时其生存期结束。而利用static修饰的局部变量却可以延长其生存期。限定访问区域被static修饰的变量及函数只能被同一文件内的代码段访问。C++中,除上述两种还有:定义静态成员变量和静态成员函数。静态成员变量或静态成员函数表示其不属于任何ー个类实例,是类的所有类实例所其有的。实现在多对象实例间进行通信,传递信息。如:#include',iostream.h"#incJude,,string.h,'classA(public:staticinta;staticintgeta();intb;intgetb(););intA::a=100;intA::geta()(returna;}intA::getb()returnb;voidmain(void)Am,n;m.b=90;cout«m.geta()«endl;cout«m.getb()«endl;cout«m.a«endl;n.a=33;n.b=44;cout<<m.geta()<<endl;〃体现共用cout«m.getb()«endl;cout«m.a«endl;//体现共用}14、C,C++的结构体有什么区别?C的结构体是不能有函数成员的,只是ー些已有数据结构组合而成,而C+俵可以。C结构体数据成员没有public,private,protected之分,C++有。C的结构体没有继承关系,C++有。注:结构体可简单理解为类的前身。15、C中的malloc和C++中的new有什么区别?malloc,free,new,delete都是用来动态申请内存和释放内存的。malloc,free是标准函数,而new,delete是运算符。前两个在C,C++中都可使用,要包含相应的头文件,可以覆盖;而后两个只属于C++,不需要头文件的支持,可以重载。Malloc要指定申请内存的大小,其申请的只是一段内存空间。New不必指定申请内存的大小,只是建立一个对象。New和delete调用对应的构造函数和析构函数。而malloc,free只是分配内存和回收内存。malloc,free返回的是void类型指针,new,delete返回的是某种数据类型指针。16、C中指针和C++引用有什么区别?引用是变量或对象的别名,不是值,不占据存储空间,只有声明没有定义。在C++中可用于:•函数参数当函数的返回值多于ー个时,可用指针实现。如:#include',iostream.h"voidswap(int*a,int*b)(inttemp;temp=*a;*b=temp;}voidmain(void)(inta=10,b=20;cout«"beforechange:,,«a«""«b«endl;swap(&a,&b);cout«"afterchange:^'«'^*'«b«endl;}结果是:beforechange:10,20afterchange:20,10也可以用引用实现,如:#include"iostream.h"voidswap(int&a,int&b)(inttemp;temp=a;a=b;b=temp;voidmain(void)inta=10,b=20;cout«"beforechange:,,«a«""«b«endl;swap(a,b);cout«"afterchange:^'«'^*'«b«endl;)结果是:beforechange:10,20afterchange:20,10引用更加简便和易理解。•指针可不初始化且初始化时,可以指向ー个地址,也可以为空。引用必须初始化且只能初始化一次。•引用之间赋值和指针之间赋值不同。指针赋值如下:intvl=7,v2=9;int*pl=&vl,*p2=&v2;pl=p2;/*p!指向变了・/引用赋值如下:intvl=7,v2=9;int&rl=vl,&r2=v2;rl=r2;/・改变的是vl的值,将r2指向的对象v2的值赋值给VI。而rl,r2仍指向原来的变量。*/•由上述例子可知,指针可以改变指向,而引用总是指向初始化时的对象。17、预处理在C/C++中预处理如宏定义、文件包含、条件编译等。简述#ifdef,#else,#endif,#ifndef的作用软件程序的升级是在已成型软件的基础上进行修改和扩充。升级工作非常复杂和烦琐,因为软件不断地升级,程序体积在不断扩大,但是老用户却不能受到影响。条件编译指令便是解决这ー问题的最佳选择。条件编译指令#ifdef,#else,#endif,#ifndef作用有:(1)利用#ifdef和#endif将某程序功能模块包括进去,以向特定用户提供该功能,在不需要时用户可轻易屏蔽。如:#ifdefMATH#include"math.c"#endif注:如果不许向别的用户提供该功能,则在编译之前将首行的MATH加一个下划线即可。(2)在子程序前加上标记,以便于追踪和调试。#ifdefDEBUGprintf(*'indebugging ");#endif(3)应对硬件的限制。由于ー些具体应用环境的硬件不一样,限于条件,本地缺乏这种设备,只能绕过硬件,直接写出预期结果。#ifdefYAN2410i=getBordNum();〃当没有YAN2410硬件时,程序调试运行时绕过此语句#elsei=0;#endif18、typedef和define有什么区别?(1)用法不同typedef是用来说明一个数据类型的别名,以增强程序的可读性。define是用来定义符号常量和带参数宏。(2)执行时间不同typedef定义是定义语句,占用运行时间。且有类型检査功能。define是预处理,只占编译时间。只是简单进行字符串的替换,不进行类型检査。(3)typedef有作用域限制,define没有,只要在声明后引用均可。#include<stdio.h>voidfl(void)(TypedefintINT;INTA=3;Printf("A:%d",A);}•编译不会通过,typedef定义的INT只限制在f1函数里。•上述例子不是很恰当,typedef一般不放在函数里,在此只是为了说明问题#include<stdio.h>voidfl(void)(#defineMAX100;}Voidmain(void)(Printf("MAX:%d",MAX);}•编译运行正确。(4)对指针的操作不同•#include<stdio.h>#definepCHARchar*typedefchar*pchar;pCHARa,b;pcharx,y;printf("sizeof(a):%d\nsizeof(b):%d\n",sizeof(a),sizeof(b));printf(Hsizeof(x):%d\nsizeof(y):%d\n",sizeof(x),sizeof(y));}结果为:Sizeof(a):4Sizeof(b):lSizeof(x):4Sizeof(y):4注意:用define定义的char・只是简单替换19、#defineCHARchar・和typedefchar*CHAR有什么区别?由define定义的类型别名可以被其他修饰符扩展如unsigned,而typedef不可。define定义的类型别名代表指针时,其连续声明的变量中只有第一个是指针,其他的均为非指针的普通变量,而typedef能够保证连续声明的所有变量都为同一类型的指针。如18.20、const(l)const用来定义ー个常量:定义时初始化,之后不能被更新。如:constdoublePI=3.14;⑵便于类型检査:用const方法可以使编译器对处理内容有更多的了解。如:voidfl(constinta)(}编译器就可以知道a在该函数中不能改变,若改变就会报错。⑶同宏定义ー样方便进行参数的修改和调整:如果想改变某个值,只需改变定义处。(4)节省空间:避免不必要的内存分配。如:#defineMAX100constintmax=100;〃不分配空间inta=max;〃为max分配空间,以后不再分配Intb=MAX;//编译时进行宏替换,为b分配空间?Intc=max;〃分配空间Intd=MAX;〃编译时进行宏替换,为d分配空间?比宏定义节省空间????????⑸为函数重载提供参考,如下:classA(voidfl(void);voidfl(void)const;〃声明为上一个函数的重载21、说明下面a的各种声明含义。Constinta;//a只读Intconsta;//a只读Constint*a;/・定义了一个指针a,这个指针指向常整形数据。即指针是普通指针,可以改变其值,但是其指向的常整形数据是不能通过指针改变的。*/Int*consta;/・定义了一个常指针a,这个指针指向整型数。即指针的值不能改变,但是指向的整型变量的值是可以改变的。*/Intconst*aconst;/・定义了一个常指针a,这个指针指向一个常整型数。即指针的值不能改变,其指向的整型数据的值也不能改变。*/22、const,define定义常量的区别常量的引入可以增强程序的可读性,可以使程序的维护和调试更加方便,使书写简便。区别:(l)const定义常量有数据类型,而define没有。⑵很多集成开发环境只支持对const定义的常量的调试,不支define定义的常量。(3)Const定义的常量是要分配内存空间的,而define定义的常量却不分配空间。23、static在C中主要用于定义全局静态变量,局部静态变量,静态函数。C++中新增了:定义静态数据成员和静态函数成员。24>volatile表示动态的,易变的。在嵌入式编程中状态寄存器变量会随时被外界条件改变,属于这种类型的变量。在多线程编程中临界变量被几个线程共享,也是易变的。25、ー个参数可以既是const又是volatile吗?•Volatile修饰的变量的值是程序不可控的,可以任何不被程序明确指明的方式改变,例如:外部端口。它的变化不用程序内部的赋值语句就可实现。编译器不会优化这种由volatile修饰的变量。Const修饰的变量在程序中是只读的,不能被改变的。但这仅限于程序内部,它可以被程序外的东西改变。例如用const修饰外部端口,程序内部不能修改它的值,但是外部却可以。但是编译器会优化掉const修饰的变量。•现在用volatile和const来同时修饰ー个变量,比如外部端口。这个变量在程序内部不能够改变,并且编译器不会对其优化,但是外部条件却可以改变。另外一种常见的情况是只读的状态寄存器。它受volatile修饰,但它却可能被意想不到地改变。可以,用const和volatile同时修饰变量,表示这人变量在程序内部是只读的,不能改变的,只在程序外部条件下改变,并且编译器不会优化这个变量。每次使用这个变量时,都要小心地去内存读取这个变量的值,而不是去寄存器读取它的备份。Volatile可用来修饰指针。常见例:子中断服务子程序修改ー个指向ー个buffer的指针时,必须用volatile来修饰这个指针。26、引用引用是指某一目标变量的别名。对引用的操作和对变量的直接操作一样。定义:数据类型&引用名=目标变量名;引用可用作:(1)函数参数在C++中大多时候引用可代替指针实现址传递。如:#include<iostream.h>voidswap(char&x,char&y)〃引用作参数(inttemp=0;temp=x;x=y;y=temp;}voidmain(void)(chara=0,b=0;cin»a»b,cout«,,beforeswap,,«endl;cout<<“a:“<<“b:“<<endl;swap(a,b);cout«nafterswap,,«endl;return;}结果:abbeforeswapa:ab:bafterswapa:bb:a注意:•引用作函数参数时,在内存中没有产生参数的副本即不分配内存空间,只是目标变量的别名。而一般变量作参数时,要给形参分配内存空间。•没有数组的引用。因为没法给若干个元素定义ー个别名。•引用的声明一定要初始化。数据类型是指目标变量的数据类型。(2)常引用定义:const数据类型&引用名=目标变量名;如:charx=l;constchar&rx=x;rx=2;〃错误,rx是只读的x=2;〃正确注意:不能通过目标变量的常引用来改变目标变量的值。(3)作函数返回值定义格式:数据类型&函数名(形参列表){函数体}例1:#include<stdio.h>inttemp;intfl(intx)(temp=(int)(x*x*3);returntemp;}int&f2(intx)(temp=(int)(x*x*3);returntemp;voidmain(void)inta=fl(5);〃系统生成要返回值的副本即临时变量int&b=fl(100);〃有时会出错。不能从被调函数中返回一个临时变量或局部变量的引用intc=f2⑸;//系统不生成返回值的副本,可以从被调函数中返回一个全局变量的引用int&d=f2(5);〃系统不生成返回值的副本,可以从被调函数中返回ー个全局变量的引用cout«a«endl;cout«c«endl;cout«d«endl;}注意:不能返回局部变量的值。局部变量在被调用函数返回后就被销毁掉,它返回的引用所指向的内存已没有任何意义,运行时会出现不可预知的错误。如:#include<iostream.h>int&fl(intx)(inttemp;temp=x;cout<<”infl:,,«endl;cout«"&tempis:,,«&temp«endl;cout«”tempis:,,«temp«endl;returntemp;voidmain(void)(int&a=fl(5);a=9;cout«,,inmain''«endl;cout«n&ais,,«&a«endl;cout«,,ais:,,«a«endl;}结果:注意:•不能返回函数内部new分配的内存的引用。•可以返回类成员的引用,但最好是常引用。27、常引用常引用的引入主要是为了避免使用变量的引用时,在不知情的情况下改变变量的值。即在很多时候,只想访问变量的值,不希望改变变量的值。常引用是唯一的选择。常引用的作用:(1)用途普通变量的只读别名,通过这个别名只能获得这个变量的值,不能通过这个别名改变这个变量的值。#include<iostream.h>voidmain(void)(charx^a';constchar&y=x;cout«,,x:,,«x«,,y:,,«y«endl;x=,b,;cout«,,x:,,<<x«,,y:,,«y«endl;y=,a,;cout«,,x:,,«x«,,y:,,«y«endl;}在VC6.0中会出现编译错误:errorc2166:Lvaluespecifiesconstobject即左值是个只读对象。(2)用于函数的形参。常引用作形参,可确保在函数内不会意外改变实参的值。28、指针说明以下声明的含义:int*p[10];定义了一个指针数组P,10个元素都是整型指针。int(*p)[10];定义了一个指向具有!0个整型元素数组的数组指针Point*p(int);定义了一个函数P,该函数有一个整型参数,返回值为整型指针。int(*p)(int);定义了一个指向函数指针P,指向的函数有一个整型参数,返回值为整型数据。int(**p)[10];等价于int(*(*p))[10].*p是数组指针,定义了一个指向含有10个整型元素数组的二级数组指针。char*(*p)[10];等价于(char*)(*p)[10]o*p是数组指针,指向含有10个元素的数组,数组元素的类型是char・〇float(*p[10])();定义了一个含有10个元素的数组p,数组的元素是函数指针,这个函数没有参数,返回类型是float型的。double*((*p)[10]);P为数组的指针,数组有10个元素,元素为double・型。short(*p)(char);P为函数指针,它指向的函数有一个char型的参数,返回值为short型数据。long(*(*p)(int,int))(int);假设pF=(*p)(int,inり,pF是个函数指针,原式变为:long(*pF)(int)。pF指向的函数有一个int型的参数,返回值为long型数据。P为函数指针,它指向的函数有两个int型参数,返回值为函数指针型数据,这个返回的函数指针指向的函数有一个int型的参数,返回值为long型数据。29、指针常量和常量指针的区别指针常量是指定义的指针只能在定义的时候初始化,之后不能改变其值。定义格式如下:数据类型・const指针变量名;const位于・右侧,说明声明的对象是ー个常量,而对象的数据类型是指针。如:chara[5]=^^abcd^^;char*constcp=a;指针常量的指向不能变,即上例中cp只能指向a,初始化指向谁就不能再改变。但其指向的对象的值是可以变的,即上例中数组a元素的值可以变。常量指针是指向常量的指针。定义格式:数据类型const・常量指针名;或:const数据类型・常量指针名;const位于指针声明符・的左侧,说明常量指针的值是可以改变的即指向可以变,但是其指向的内容是不能用这个指针改变的,可以自己改变。30、(1)#include<iostream.h>voidmain(void)(charsl[]=^^abcd^^;chars2[]=^^abcd^^;constchars3[]="abcd'';constchars4[]="abcd”;constchar*s5="abcd”;constchar*s6="abcd”;char*s7="abcd”;char*s8="abcd”;cout«(sl==s2)«endl;cout«(s3==s4)«endl;cout«(s5==s6)«endl;cout«(s7==s8)«endl;结果:0011sl,s2,s3,s4,是数组,有各自的内存空间,所以地址不等。s5,s6,s7,s8是指针,指向相同的常量。字符串常量"abed”产生一个临时指针变量&(“abcd”)。所以地址相等。(2)写出结果#include<iostream.h>voidmain(void)(intb=0;inta[5]={0,l,2,3,4);for(inti=0;i<5;)(i=a[i+l];cout«a[i]«endl;}return;}会下标越界,但编译器不会报错,C/C++不进行数组越界检查。结果是:12340123401234 (死循环)(3)程序是否有错#defineMAX255#include<stdio.h>voidmain(void)unsignedcharstr[MAX],i;for(i=0;i<=MAX;i++)(str[i]=i;printf(4<%d\n”,str[i]);)}可以赋i为255,再加1,看看结果。该程序会出现下标越界及死循环。同上。在0〜255之间循环。31、a为数组名,a和&a有什么区别?写出结果:#include<stdio.h>voidmain(void)(inta[5]={l,23,4,5);int*ptr=(int*)(&a+l);printf(u%d,%d\n,,,*(a+l),*(ptr-l));return;a与&a是不同的。a+1是数组的首地址加1,是数组的第二个元素a[l]的地址。&a+l系统会主为是数组a的首地址加上ー个数组a的偏移,即偏移ー个数组的大小。•数组名a可以作为数组的首地址,&a是数组的指针。结果为:2,532、解析(*(void(*)())0)();void(*0)():是ー个返回值为void,参数为空的函数指针0.(void(*)())0:把〇强制转换成返回值为void,参数为空的函数指针。*(void(*)())0:加・表示整个是ー个返回值为void,无参数,且起始地址为0的函数的名字。(*(void(*)())0)():上述函数名的调用。33、野指针是怎么产生的,如何避免?野指针是指指向不可用内存的指针。通常对这种指针进行操作时,程序会发生不可预知的错误。在以下三种情况发生:(1)指针变量声明时没有被初始化。任何指针变量刚被创建时都不会自动初始化为NULL指针,它的默认值是随机的,它会指向ー个随机地址。通常在定义指针时要求赋值为NULLo#include<iostream.h>typedefint*pint;voidswap(int*pl,int*p2)int*p;〃没有初始化,成为野指针。改为intp;后面一起改*p=*pl;*pl=*p2;*p2=*p;}voidmain(void)(inta=l,b=3;pintpl=&a,p2=&b;cout«,,a:,,«*pl«,,b:,,«*p2«endl;swap(pl,p2);cout«,,a:,,«*pl«,,b:,,«*p2«endl;return;}(2)指针p被free或delete之后,没有置为NULL,让人误以为p是个合法的指针。为避免这种情况最好在free或delete后赋值为NULL.(3)指针操作超越了变量的作用范围。如:#include<iostream.h>classApublic:voidfunc(void)(value=3;cout«,,infunofA,,«endl;}public:intvalue;);voidf(A*p){Aa;p=&a;p->func();}voidmain(void){A*P;f(P);p->func();〃出错return;因为在f中p指向了A的对象a,并调用了func,输出infunofA。在f结束后,a被释放,p指向了“垃圾”内存。但在main中又用p调用func。由于p指向的内存不可用,导致内存操作错误。解决方法:在变量的作用域结束前释放掉变量的地址空间并让指针指向NULL.数据结构常见面试题1、链表和数组的区别•存储形式:链表可以是ー块不连续的动态空间,长度可变;数组要求是ー块连续空间,声明时要确定长度。•数据访问:数组可随机访问,速度快,査找操作直接使用偏移地址;链表则要顺序检索,效率低。数据插入和删除:链表可快速插入和删除;数组则可能要移动大量数据。越界问题:链表不存在越界问题;而数组有。•占用空间:存储相同数据时,链表要比数组占用更多空间,因为它除了存数据还要存指针。2、快速寻找单链表中间结点。方法:•双指针同时从头结点开始遍历。•快指针每次移动两个结点,慢指针每次移动ー个结点。•快指针到链表尾部时,当链表长度为奇数时,慢指针指向的即是链表中间指针。当链表长度为偶数时,慢指针指向的结点和慢指针指向结点的下个结点都是链表的中间结点。算法设计:typedefstructNODE(inta;structnode*next;}NODE;NODE*middle(lnode*head){NODE*fast,*slow,*p;if(head==NULL)returnNULL;fast=slow=head;while(!(p=fast・>next)&&!p->next)〃?是II还是&&slow=slow->next;fast=p->next;)returnslow;)3、设计算法将单链表反序过程:把头结点(无头指针)指向空,后面的结点的next指针指向它前面的ー个元素,最后尾结点成了头结点。算法:(1)循环算法Listreverse(Listn)(if(!n)returnn;listcur=n->next;listpre=n;listtemp;pre->next=NULL;while(NULL!=cur->next)(temp=cur;temp->next=pre;pre=temp;cur=cur->next;)returntemp;〃返回头指针)(2)递归算法List*reverse(List*oldList,List*newHead=NULL)(List*next=oldList->next;oldList->next=newHead;newHead=oldList;return(next==NULL)?newHead:reverse(t,newHead);)4^单循环链表单循环链表的尾结点指针指向首结点,形成一个环,可以从链表中的任一结点出发,访问链表中的所有结点。带环单向链表是指环的起点不是链表第一个结点,即ー个单向链表和一个环形链表的结合体。设计一个程序,用键盘输入的ー些数字创建一个单向循环链表,求出链表的和度,打印链表各个元素。之后可以根据需求把这个循环链表改装成单向链表或带环的单向链表。〃结点结构typedefstructnode{intdata;structnode*next;}Lnode,*LinkList;〃单向循环链表voidCreatLin

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论