《c,c++面试题 .pdf》由会员分享,可在线阅读,更多相关《c,c++面试题 .pdf(46页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、1.C+的类和 C里面的 struct有什么区别?struct成员默认访问权限为public,而 class 成员默认访问权限为private 2.析构函数和虚函数的用法和作用析构函数是在对象生存期结束时自动调用的函数,用来释放在构造函数分配的内存。虚函数是指被关键字virtual说明的函数,作用是使用C+语言的多态特性3.全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的?1)全局变量的作用用这个程序块,而局部变量作用于当前函数2)前者在内存中分配在全局数据区,后者分配在栈区3)生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁,局部变量在局部函数内部,甚至局
2、部循环体等内部存在,退出就不存在4)使用方式不同:通过声明后全局变量程序的各个部分都可以用到,局部变量只能在局部使用4.有 N个大小不等的自然数(1N),请将它们由小到大排序.要求程序算法:时间复杂度为 O(n),空间复杂度为O(1)。void sort(int e,int n)int i;int t;for(i=1;i t=eei;eei=ei;ei=t;5.堆与栈的去区别A.申请方式不同Stack 由系统自动分配,而heap需要程序员自己申请,并指明大小。B.申请后系统的响应不同Stack:只要栈的剩余空间大于申请空间,系统就为程序提供内存,否则将抛出栈溢出异常Heap:当系统收到程序申请
3、时,先遍历操作系统中记录空闲内存地址的链表,寻找第一个大于所申请空间的堆结点,然后将该结点从空间结点链表中删除,并将该结点的空间分配给程序。另外,大多数系统还会在这块内存空间中的首地址处记录本次分配的大小,以便于 delete 语句正确释放空间。而且,由于 找到的堆结点的大小不一定正好等于申请的大小,系统会自动将多余的那部分重新放入空闲链表。C.申请大小限制的不同Stack:在 windows下,栈的大小是 2M(也可能是 1M它是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。Heap:堆是向高地址扩展的数据结构,是不连续的内存
4、区域。这是由于系统是用名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 46 页 -链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。D.申请效率的比较:栈由系统自动分配,速度较快。但程序员是无法控制的。堆是由 new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。另外,在 WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。E.堆和栈
5、中的存储内容栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的 C编译器 中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。6.含参数的宏与函数的优缺点宏:优点:在预处理阶段完成,不占用编译时间,同时,省去了函数调用的开销,运行效率高缺点:不进行类型检查,多次宏替换会导致代码体积变大,而且由于宏
6、本质上是字符串替换,故可能会由于一些参数的副作用导致得出错误的结果。函数:优点:没有带参数宏可能导致的副作用,进行类型检查,计算的正确性更有保证。缺点:函数调用需要参数、返回地址等的入栈、出栈开销,效率没有带参数宏高PS:宏与内联函数的区别内联函数和宏都是在程序出现的地方展开,内联函数不是通过函数调用实现的,是在调用该函数的程序处将它展开(在编译期间完成的);宏同样是;不同的是:内联函数可以在编译期间完成诸如类型检测,语句是否正确等编译功能;宏就不具有这样的功能,而且宏展开的时间和内联函数也是不同的(在运行期间展开)7.Windows 程序的入口是哪里?写出Windows消息机制的流程Wind
7、ows程序的入口是 WinMain()函数。Windows应用程序消息处理机制:A.操作系统接收应用程序的窗口消息,将消息投递到该应用程序的消息队列中B.应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息,取出消息后,应用程序可以对消息进行一些预处理。C.应用程序调用 DispatchMessage,将消息回传给操作系统。D.系统利用 WNDCLASS结构体的 lpfnWndProc 成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理。8.如何定义和实现一个类的成员函数为回调函数A.什么是回调函数?简而言之,回调函数就是被调用者回头调用调用者的函数。使用回调函
8、数实际上就是在调用某个函数(通常是 API 函数)时,将自己的一个名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 46 页 -函数(这个函数为回调函数)的地址作为参数传递给那个被调用函数。而该被调用函数在需要的时候,利用传递的地址调用回调函数。回调函数,就是由你自己写的,你需要调用另外一个函数,而这个函数的其中一个参数,就是你的这个回调函数名。这样,系统在必要的时候,就会调用你写的回调函数,这样你就可以在回调函数里完成你要做的事。B.如何定义和实现一个类的成员函数为回调函数要定义和实现一个类的成员函数为回调函数需要做三件事:a声明;b定义;c设置触发条件,就是在你的函数中把你的回
9、调函数名作为一个参数,以便系统调用如:一、声明回调函数类型typedef void(*FunPtr)(void);二、定义回调函数class A public:A();static void callBackFun(void)/回调函数,必须声明为static coutcallBackFun=EPSINON)&(x=”或“=”此类形式。如下是错误的写法,不得分。if(x=0.0)if(x!=0.0)请写出 char*p 与“零值”比较的 if 语句。(3分)标准答案:if(p=NULL)if(p!=NULL)如下写法均属不良风格,不得分。if(p=0)if(p!=0)if(p)if(!)二、以
10、下为 Windows NT下的 32 位 C+程序,请计算 sizeof的值(10 分)请计算 void Func(char str100)sizeof(str)=4(2 分)void*p=malloc(100);请计算sizeof(p)=4(2 分)三、简答题(25 分)1、头文件中的 ifndef/define/endif 干什么用?(5 分)答:防止该头文件被重复引用。2、#include 和#include“filename.h”有什么区别?(5 分)答:对于#include,编译器从标准库路径开始搜索 filename.h 名师资料总结-精品资料欢迎下载-名师精心整理-第 9 页,共
11、 46 页 -对于#include“filename.h”,编译器从用户的工作路径开始搜索filename.h 3、const 有什么用途?(请至少说明两种)(5 分)答:(1)可以定义 const 常量(2)const 可以修饰函数的参数、返回值,甚至函数的定义体。被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。4、在 C+程序中调用被 C 编译器编译后的函数,为什么要加extern“C”?(5分)答:C+语言支持函数重载,C语言不支持函数重载。函数被 C+编译后在库中的名字与 C语言的不同。假设某个函数的原型为:void foo(int x,int y);该
12、函数被 C编译器编译后在库中的名字为_foo,而 C+编译器则会产生像_foo_int_int之类的名字。C+提供了 C连接交换指定符号 extern“C”来解决名字匹配问题。5、请简述以下两个for 循环的优缺点(5 分)for(i=0;i if(condition)DoSomething();else DoOtherthing();if(condition)for(i=0;i DoSomething();else for(i=0;i DoOtherthing();优点:程序简洁缺点:多执行了 N-1 次逻辑判断,并且打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。优
13、点:循环的效率高缺点:程序不简洁四、有关内存的思考题(每小题5 分,共 20 分)void GetMemory(char*p)名师资料总结-精品资料欢迎下载-名师精心整理-第 10 页,共 46 页 -p=(char*)malloc(100);void Test(void)char*str=NULL;GetMemory(str);strcpy(str,“hello world”);printf(str);请问运行 Test 函数会有什么样的结果?答:程序崩溃。因为 GetMemory并不能传递动态内存,Test 函数中的 str一直都是 NULL。strcpy(str,“hello world
14、”);将使程序崩溃。char*GetMemory(void)char p=“hello world”;return p;void Test(void)char*str=NULL;str=GetMemory();printf(str);请问运行 Test 函数会有什么样的结果?答:可能是乱码。因为 GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。void GetMemory2(char*p,int num)*p=(char*)malloc(num);void Test(void)char*str=NULL;GetMemory(&
15、str,100);strcpy(str,“hello”);printf(str);请问运行 Test 函数会有什么样的结果?答:名师资料总结-精品资料欢迎下载-名师精心整理-第 11 页,共 46 页 -(1)能够输出 hello(2)内存泄漏void Test(void)char*str=(char*)malloc(100);strcpy(str,“hello”);free(str);if(str!=NULL)strcpy(str,“world”);printf(str);请问运行 Test 函数会有什么样的结果?答:篡改动态内存区的内容,后果难以预料,非常危险。因为 free(str);之
16、后,str 成为野指针,if(str!=NULL)语句不起作用。五、编写 strcpy函数(10 分)已知 strcpy函数的原型是char*strcpy(char*strDest,const char*strSrc);其中 strDest是目的字符串,strSrc是源字符串。(1)不调用 C+/C的字符串库函数,请编写函数 strcpy char*strcpy(char*strDest,const char*strSrc);assert(strDest!=NULL)&(strSrc!=NULL);/2分char*address=strDest;/2分while(*strDest+=*strS
17、rc+)!=0)/2分NULL;return address;/2分 (2)strcpy 能把 strSrc的内容复制到 strDest,为什么还要 char*类型的返回值?答:为了实现链式表达式。/2分例如 int length=strlen(strcpy(strDest,“hello world”);六、编写类 String的构造函数、析构函数和赋值函数(25 分)已知类 String的原型为:class String public:String(const char*str=NULL);/普通构造函数名师资料总结-精品资料欢迎下载-名师精心整理-第 12 页,共 46 页 -String
18、(const String&other);/拷贝构造函数 String(void);/析构函数String&operate=(const String&other);/赋值函数private:char*m_data;/用于保存字符串;请编写 String的上述 4 个函数。标准答案:/String的析构函数String:String(void)/3分 delete m_data;/由于 m_data 是内部数据类型,也可以写成 delete m_data;/String的普通构造函数String:String(const char*str)/6分 if(str=NULL)m_data=new
19、char1;/若能加 NULL 判断则更好*m_data=0;else int length=strlen(str);m_data=new charlength+1;/若能加 NULL 判断则更好strcpy(m_data,str);/拷贝构造函数String:String(const String&other)/3分 int length=strlen(other.m_data);m_data=new charlength+1;/若能加 NULL 判断则更好strcpy(m_data,other.m_data);/赋值函数String&String:operate=(const String
20、&other)/13分/(1)检查自赋值 /4分if(this=&other)return*this;名师资料总结-精品资料欢迎下载-名师精心整理-第 13 页,共 46 页 -/(2)释放原有的内存资源 /3分delete m_data;/(3)分配新的内存资源,并复制内容/3分int length=strlen(other.m_data);m_data=new charlength+1;/若能加 NULL 判断则更好strcpy(m_data,other.m_data);/(4)返回本对象的引用 /3分return*this;、许多面试题看似简单,却需要深厚的基本功才能给出完美的解答。企业
21、要求面试者写一个最简单的strcpy函数都可看出面试者在技术上究竟达到了怎样的程度,我们能真正写好一个strcpy函数吗?我们都觉得自己能,可是我们写出的strcpy很可能只能拿到 10 分中的 2 分。读者可从本文看到strcpy函数从 2 分到 10 分解答的例子,看看自己属于什么样的层次。此外,还有一些面试题考查面试者敏捷的思维能力。分析这些面试题,本身包含很强的趣味性;而作为一名研发人员,通过对这些面试题的深入剖析则可进一步增强自身的内功。2.找错题试题:void test1()char string10;char*str1=“0123456789;strcpy(string,str1
22、);试题 2:void test2()名师资料总结-精品资料欢迎下载-名师精心整理-第 14 页,共 46 页 -char string10,str110;int i;for(i=0;i10;i+)str1i=a;strcpy(string,str1);试题 3:void test3(char*str1)char string10;if(strlen(str1)=10)strcpy(string,str1);解答:试题 1 字符串 str1 需要 11 个字节才能存放下(包括末尾的0),而 string只有 10 个字节的空间,strcpy 会导致数组越界;对试题 2,如果面试者指出字符数组s
23、tr1 不能在数组内结束可以给3 分;如果面试者指出 strcpy(string,str1)调用使得从 str1 内存起复制到 string内存起所复制的字节数具有不确定性可以给7 分,在此基础上指出库函数strcpy工作方式的给 10 分;对试题 3,if(strlen(str1)=10)应改为 if(strlen(str1)10),因为 strlen的结果未统计 0 所占用的 1 个字节。名师资料总结-精品资料欢迎下载-名师精心整理-第 15 页,共 46 页 -剖析:考查对基本功的掌握:(1)字符串以0结尾;()对数组越界把握的敏感度;()库函数 strcpy的工作方式,如果编写一个标准
24、strcpy函数的总分值为10,下面给出几个不同得分的答案:2 分void strcpy(char*strDest,char*strSrc)while(*strDest+=*strSrc+)!=0);4 分void strcpy(char*strDest,const char*strSrc)/将源字符串加 const,表明其为输入参数,加2 分 while(*strDest+=*strSrc+)!=0);7 分void strcpy(char*strDest,const char*strSrc)/对源地址和目的地址加非0 断言,加 3 分assert(strDest!=NULL)&(strSr
25、c!=NULL);while(*strDest+=*strSrc+)!=0);名师资料总结-精品资料欢迎下载-名师精心整理-第 16 页,共 46 页 -10 分/为了实现链式操作,将目的地址返回,加3 分!char*strcpy(char*strDest,const char*strSrc)assert(strDest!=NULL)&(strSrc!=NULL);char*address=strDest;while(*strDest+=*strSrc+)!=0);return address;从 2 分到 10 分的几个答案我们可以清楚的看到,小小的 strcpy竟然暗藏着这么多玄机,真不是
26、盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!()对 strlen的掌握,它没有包括字符串末尾的0。读者看了不同分值的strcpy版本,应该也可以写出一个10 分的 strlen函数了,完美的版本为:int strlen(const char*str)/输入参数 const assert(strt!=NULL);/断言字符串地址非0 int len;while(*str+)!=0)len+;return len;名师资料总结-精品资料欢迎下载-名师精心整理-第 17 页,共 46 页 -试题 4:void GetMemory(char*p)p=(char*)malloc(100);
27、void Test(void)char*str=NULL;GetMemory(str);strcpy(str,“hello world”);printf(str);试题 5:char*GetMemory(void)char p=“hello world”;return p;void Test(void)char*str=NULL;str=GetMemory();printf(str);名师资料总结-精品资料欢迎下载-名师精心整理-第 18 页,共 46 页 -试题 6:void GetMemory(char*p,int num)*p=(char*)malloc(num);void Test(v
28、oid)char*str=NULL;GetMemory(&str,100);strcpy(str,“hello”);printf(str);试题 7:void Test(void)char*str=(char*)malloc(100);strcpy(str,“hello”);free(str);,/省略的其它语句 解答:试题 4 传入中 GetMemory(char*p)函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值,执行完名师资料总结-精品资料欢迎下载-名师精心整理-第 19 页,共 46 页 -char*str=NULL;GetMemory(str);后的 str仍
29、然为 NULL;试题 5 中char p=“hello world”;return p;的 p 数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。试题 6 的 GetMemory避免了试题 4 的问题,传入 GetMemory的参数为字符串指针的指针,但是在 GetMemory中执行申请内存及赋值语句、1.以下三条输出语句分别输出什么?C 易 char str1=“abc”;char str2=“abc”;const char str3=“abc”;const char str4=“abc”;const char*str5=“ab
30、c”;const char*str6=“abc”;cout boolalpha (str1=str2)endl;/输出什么?cout boolalpha (str3=str4)endl;/输出什么?cout boolalpha (str5=str6)endl;/输出什么?2.非 C+内建型别 A 和 B,在哪几种情况下B能隐式转化为 A?C+中等 答:a.class B:public A ,/B公有继承自 A,可以是间接继承的b.class B operator A();/B实现了隐式转化为A的转化c.class A A(const B&);/A实现了 non-explicit的参数为 B(可
31、以有其他带默认值的参数)构造函数d.A&operator=(const A&);/赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个3.以下代码中的两个sizeof用法有问题吗?C 易 void UpperCase(char str)/将 str 中的小写字母转换成大写字母 for(size_t i=0;i if(a=stri&stri=z)stri-=(a-A);char str=aBcDe;cout str字符长度为:sizeof(str)/sizeof(str0)endl;名师资料总结-精品资料欢迎下载-名师精心整理-第 20 页,共 46 页 -UpperCase(str);cou
32、t str endl;1.求下面函数的返回值(微软)int func(x)int countx=0;while(x)countx+;x=x&(x-1);return countx;假定 x=9999。答案:8 思路:将 x 转化为 2 进制,看含有的 1 的个数。2.什么是“引用”?申明和使用“引用”要注意哪些问题?答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进行初始化。引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表
33、示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。3.将“引用”作为函数参数有哪些特点?(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传
34、递的数据较大时,用引用比用一般变量传递参数的效率 和所占空间都好。(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用*指针变量名 的形 式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。4.在什么时候需要使用“常引用”?如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const 类型标识符&引用名=目标变量名;例 1 int a;const int&ra=a;ra=1;/错误a=1;/正确名
35、师资料总结-精品资料欢迎下载-名师精心整理-第 21 页,共 46 页 -例 2 string foo();void bar(string&s);那么下面的表达式将是非法的:bar(foo();bar(hello world);原因在于 foo()和hello world串都会产生一个临时对象,而在C+中,这些临时对象都是 const 类型的。因此上面的表达式就是试图将一个const 类型的对象转换为非 const 类型,这是非法的。引用型参数应该在能被定义为const 的情况下,尽量定义为const。5.将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?格式:类型标识符&函数名(形参
36、列表及类型说明)/函数体 好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!注意事项:(1)不能返回局部变量的引用。这条可以参照Effective C+1的 Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了 无所指的引用,程序会进入未知状态。(2)不能返回函数内部new分配的内存的引用。这条可以参照 Effective C+1的 Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部 new分配内存的引用)
37、,又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由 new分配)就无法释放,造成memory leak。(3)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C+1 的 Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。(4)流操作符重载返回值申明为“引用”的
38、作用:流操作符,这两个操作符常常希望被连续使用,例如:cout hello endl;因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两 个操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用 操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C+语言中引入引用这个概念的原因吧。赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x=j=10;或者
39、(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。例 3#include int&put(int n);名师资料总结-精品资料欢迎下载-名师精心整理-第 22 页,共 46 页 -int vals10;int error=-1;void main()put(0)=10;/以 put(0)函数值作为左值,等价于vals0=10;put(9)=20;/以 put(9)函数值作为左值,等价于vals9=20;coutVALS0;cout=0&n=9)return valsn;else coutsubscript error;retur
40、n error;(5)在另外的一些操作符中,却千万不能返回引用:+-*/四则运算符。它们不能返回引用,Effective C+1 的 Item23 详 细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一个静态对象引用。根据前面提到的引用作为返回值的三个规则,第 2、3 两个方案都被否决了。静态对象的引用又因为(a+b)=(c+d)会永远为 true 而导致错误。所以可选的只剩下返回一个对象了。6.引用与多态的关系?引用是除指针外另一个可以产生多态
41、效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。例 4 Class A;Class B:Class A.;B b;A&ref=b;7.引用与指针的区别是什么?指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。此外,就是上面提到的对函数传ref 和 pointer的区别。8.什么时候需要“引用”?流操作符、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用9.结构与联合有和区别?1.结构和联合都是由多个不同的数据类型成员组成,但在任何同一时刻,
42、联合中只存放了一个被选中的成员(所有成员共用一块地址空间),而结构的所有成员都存在(不同成员的存放地址不同)。2.对于联合的不同成员赋值,将会对其它成员重写,原来成员的值就不存在了,而对于结构的不同成员赋值是互不影响的。10.下面关于“联合”的题目的输出?a)#include union 名师资料总结-精品资料欢迎下载-名师精心整理-第 23 页,共 46 页 -int i;char x2;a;void main()a.x0=10;a.x1=1;printf(“%d”,a.i);答案:266(低位低地址,高位高地址,内存占用情况是Ox010A)b)main()union int i;struc
43、t char first;char second;half;number;number.i=0 4241;printf(“%c%cn”,number.half.first,mumber.half.second);number.half.first=a;number.half.second=b;printf(“%x n”,number.i);getch();答案:AB(041 对应A,是低位;Ox42对应B,是高位)6261(number.i和 number.half共用一块地址空间)11.已知 strcpy 的函数原型:char*strcpy(char*strDest,const char*s
44、trSrc)其中 strDest 是目的字符串,strSrc 是源字符串。不调用 C+/C 的字符串库函数,请编写函数 strcpy。答案:char*strcpy(char*strDest,const char*strSrc)if(strDest=NULL|strSrc=NULL)return NULL;if(strDest=strSrc)return strDest;char*tempptr=strDest;while(*strDest+=*strSrc+)!=0);名师资料总结-精品资料欢迎下载-名师精心整理-第 24 页,共 46 页 -return tempptr;12.已知 Stri
45、ng类定义如下:class String public:String(const char*str=NULL);/通用构造函数String(const String&another);/拷贝构造函数 String();/析构函数String&operater=(const String&rhs);/赋值函数private:char*m_data;/用于保存字符串;尝试写出类的成员函数实现。答案:String:String(const char*str)if(str=NULL)/strlen在参数为 NULL时会抛异常才会有这步判断 m_data=new char1;m_data0=0;else
46、 m_data=new charstrlen(str)+1;strcpy(m_data,str);String:String(const String&another)m_data=new charstrlen(another.m_data)+1;strcpy(m_data,other.m_data);String&String:operator=(const String&rhs)if(this=&rhs)return*this;delete m_data;/删除原来的数据,新开一块内存m_data=new charstrlen(rhs.m_data)+1;strcpy(m_data,rhs
47、.m_data);return*this;String:String()名师资料总结-精品资料欢迎下载-名师精心整理-第 25 页,共 46 页 -delete m_data;13.h头文件中的 ifndef/define/endif 的作用?答:防止该头文件被重复引用。14.#include 与#include“file.h”的区别?答:前者是从 Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用 file.h。15.在 C+程序中调用被 C 编译器编译后的函数,为什么要加extern“C”?首先,作为 extern 是 C/C+语言中表明函数和全
48、局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字 extern 声明。例如,如果模块 B欲引用该模块 A中定义的全局变量和函数时只需包含模块 A 的头文件即可。这样,模块 B中调用模块 A中的函数时,在编译阶段,模块 B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数extern“C”是连接申明(linkage declaration),被 extern“C”修饰的变量和函数是按照 C语言方式编译和连接的,来看看 C+中对类似 C
49、的函数是怎样编译的:作为一种面向对象的语言,C+支持函数重载,而过程式语言C则不支持。函数被 C+编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo(int x,int y);该函数被 C编译器编译后在符号库中的名字为_foo,而 C+编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C+就是靠这种机制来实现函数重载的。例如,在C+中,函数 void foo(int x,int y)与
50、void foo(int x,float y)编译生成的符号是不相同的,后者为_foo_int_float。同样地,C+中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以”.”来区分。而 本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。未加 extern“C”声明时的连接方式假设在 C+中,模块 A的头文件如下:/模块 A头文件moduleA.h#ifndef MODULE_A_H#define MODULE_A_H int foo(int x,int y);