ImageVerifierCode 换一换
格式:DOCX , 页数:79 ,大小:873.27KB ,
资源ID:3566265      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3566265.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(程序员面试题整理非算法题.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

程序员面试题整理非算法题.docx

1、程序员面试题整理非算法题1.设置地址为0x67a9的整型变量的值为0xaa66 int *ptr; ptr = (int *)0x67a9; *ptr = 0xaa66; 说明:这道题就是强制类型转换的典型例子,无论在什么平台地址长度和整型数据的长度是一样的,即一个整型数据可以强制转换成地址指针类型,只要有意义即可。2. 函数传参获取数组长度的方法template void printlen(T (&c)N) coutclength: sizeof(c)endl; coutNendl;int main(int argc, char *argv) int p=1, 2, 3, 4, 5; pri

2、ntlen(p);这是一种非类型模板形参,在需要常量表达式的时候可使用非类型模板形参。如上例,当调用printlen函数时编译器从数组实参中读取int N的值3.memset 和 memcpy#include memcpy 原型:extern void *memcpy(void *dest, void *src, unsigned int count); 功能:由src所指内存区域复制count个字节到dest所指内存区域。 说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。 memset 包含:extern void *memset(void *buffer, int

3、c, int count); 功能:把buffer所指内存区域的前count个字节设置成字符c。 说明:返回指向buffer的指针。4. C+的空类有哪些成员函数 缺省构造函数。 缺省拷贝构造函数。 缺省析构函数。 缺省赋值运算符。 缺省取址运算符。 缺省取址运算符 const。 5. 写出float x 与“零值”比较的if语句。 if(x0.000001&x-0.000001)6. Internet采用哪种网络协议?该协议的主要层次结构? Tcp/Ip协议 主要层次结构为: 应用层/传输层/网络层/数据链路层/物理层7.Internet物理地址和IP地址转换采用什么协议? ARP (Add

4、ress Resolution Protocol)(地址解析協議)8.IP地址的编码分为哪俩部分? IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。9.变量的声明和定义有什么区别 为变量分配地址和存储空间的称为定义,不分配地址的称为声明。一个变量可以在多个地方声明,但是只在一个地方定义。加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。10. sizeof和strlen的区别 sizeof和strlen有以下区别: sizeof是一个操作符,strlen是库函数。 sizeof的参数可以是数据的类型,也可以

5、是变量,而strlen只能以结尾为0的字符串作参数。 编译器在编译时就计算出了sizeof的结果。而strlen函数必须在运行时才能计算出来。并且sizeof计算的是数据类型占内存的大小,而strlen计算的是字符串实际的长度。 数组做sizeof的参数不退化,传递给strlen就退化为指针了。 11. 中的malloc和中的new有什么区别malloc和new有以下不同:(1)new、delete 是操作符,可以重载,只能在C+中使用。(2)malloc、free是函数,可以覆盖,C、C+中都可以使用。(3)new 可以调用对象的构造函数,对应的delete调用相应的析构函数。(4)mall

6、oc仅仅分配内存,free仅仅回收内存,并不执行构造和析构函数(5)new、delete返回的是某种数据类型指针,malloc、free返回的是void指针12.一个指针可以是volatile吗volatile类似于大家所熟知的const也是一个类型修饰符。volatile是给编译器的指示来说明对它所修饰的对象不应该执行优化。volatile的作用就是用来进行多线程编程。可以,因为指针和普通变量一样,有时也有变化程序的不可控性。常见例:子中断服务子程序修改一个指向一个buffer的指针时,必须用volatile来修饰这个指针13.static有什么用途?对于局部变量改变其生存期,对于全局变量改

7、变其可见性主要从两个方面考虑:(1)静态存储:a. 函数体内static变量的作用范围为该函数体,该内存在静态数据区上分配且只被分配一次,下次再调用该函数时依然维持上一次的值。b. 类中的static成员变量属于整个类所有,对类的所有对象只有一份拷贝c. 在类中的static成员函数属于整个类所拥有,这个函数不接受this指针,因而只能访问类的static成员变量。(2)控制名字可见性a. 在模块内的static全局变量可以被模块内的所有函数访问,但是不能被模块外的其他函数访问b. 在模块内的static成员函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内。14.引

8、用与指针有什么区别 1) 引用必须被初始化,指针不必。 2) 引用初始化以后不能被改变,指针可以改变所指的对象。 3) 不存在指向空值的引用,但是存在指向空值的指针。15.描述实时系统的基本特性在特定时间内完成特定的任务,实时性与可靠性。16. 简述C、C+程序编译的内存分配情况C、C+中内存分配方式可以分为三种:(1)从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量等。(2)在栈上分配:在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运

9、算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(3)从堆上分配:即动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活。如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块。一个C、C+程序编译时内存分为5大存储区:堆区、栈区、全局区、文字常量区、程序代码区17. 谈谈你对拷贝构造函数和赋值运算符的认识 拷贝构造函数和赋值运算符重载有以下两个不同之处: (1)拷贝构造函数生成新的类对象,而赋值运算符

10、不能。 (2)由于拷贝构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验源对象是否和新建对象相同。而赋值运算符则需要这个操作,另外赋值运算中如果原来的对象中有内存分配要先把内存释放掉 注意:当有类中有指针类型的成员变量时,一定要重写拷贝构造函数和赋值运算符,不要使用默认的。18. 不能被继承的类(1)构造函数private此时我们可以通过static成员函数获得该类的实例(我们只能得到位于堆上的实例)class FinalClass1public : static FinalClass1* GetInstance() return new FinalClass1; static

11、 void DeleteInstance( FinalClass1* pInstance) delete pInstance; pInstance = 0; private : FinalClass1() FinalClass1() ;(2)想法:实现一个和一般类除了不能被继承之外其他用法都一样的类template class MakeFinal friend T;private : MakeFinal() MakeFinal() ;class FinalClass2 : virtual public MakeFinalpublic : FinalClass2() FinalClass2()

12、;此时FinalClass2就不能再被继承了,由于类 FinalClass2 是从类 MakeFinal 虚继承过来的,在调用 Try 的构造函数的时候,会直接跳过 FinalClass2 而直接调用 MakeFinal 的构造函数。(虚继承的一个特征就是虚基类的构造函数由最终子类负责构造)非常遗憾的是, Try 不是 MakeFinal 的友元,因此不能调用其私有的构造函数。基于上面的分析,试图从 FinalClass2 继承的类,一旦实例化,都会导致编译错误,因此是 FinalClass2 不能被继承。这就满足了我们设计要求。19. 访问基类的私有虚函数 很好的题目,借这个题目学习虚函数。

13、解题思路就是:虽然不能通过对象调用这个虚函数,但是因为虚函数会在子类的那段内存中保存虚函数表的入口地址,拿到虚函数的地址就可以转换成函数指针来调用他。下面主要解释这一行代码:pFun = ( Fun )*( ( int* ) * ( int* )( &b ) + i );(1)在子类内存空间中最开始(就是子类对象的地址&b)的地方存了一个指向虚函数表的指针(这里的最开始的说法应该是大多数编译器的做法),为了获得这个指向虚函数表的指针,需要做这个操作*(int*)&b,解释:对象b的地址强制转换成一个int指针(因为地址都是整型数),然后再解引用该指针获得虚表的指针值。(2)再做一次(int*)

14、获得虚表首地址的值,然后+i,每次+1都指向下一个虚函数的入口地址(3)最后(Fun),将虚函数入口地址强制转换为函数指针,用函数指针来完成这个私有虚函数的调用。#include class A virtual void g() cout A:g endl; private: virtual void f() cout A:f endl; ; class B : public A void g() cout B:g endl; virtual void h() cout B:h endl; ; typedef void( *Fun )( void ); void main() B b; Fun

15、 pFun; for(int i = 0 ; i 3; i+) pFun = ( Fun )*( ( int* ) * ( int* )( &b ) + i ); pFun(); 20. 类成员函数的重载、重写和隐藏成员函数被重载的特征(1)相同的范围(在同一个类中);(2)函数名字相同;(3)参数不同;(4)virtual 关键字可有可无。覆盖是指派生类函数覆盖基类函数,特征是(1)不同的范围(分别位于派生类与基类);(2)函数名字相同;(3)参数相同;(4)基类函数必须有virtual 关键字。“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下(1)如果派生类的函数与基类的函数同名

16、,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)21.简述多态实现的原理 编译器发现一个类中有虚函数,便会立即为此类生成虚函数表 vtable。虚函数表的各表项为指向对应虚函数的指针。编译器还会在此类中隐含插入一个指针vptr(对vc编译器来说,它插在类的第一个位置上)指向虚函数表。调用此类的构造函数时,在类的构造函数中,编译器会隐含执行vptr与vtable的关联代码,将vptr指向对应的vtable,将类与此类

17、的vtable联系了起来。另外在调用类的构造函数时,指向基础类的指针此时已经变成指向具体的类的this指针,这样依靠此this指针即可得到正确的vtable,。如此才能真正与函数体进行连接,这就是动态联编,实现多态的基本原理。 22. inline使用内联函数应注意的事项内联函数具有一般函数的特性,它与一般函数所不同之处只在于函数调用的处理。一般函数进行调用时,要将程序执行权转到被调用函数中,然后再返回到调用它的函数中;而内联函数在调用时,是将调用表达式用内联函数体来替换。在使用内联函数时,应注意如下几点:1.在内联函数内不允许用循环语句和开关语句。如果内联函数有这些语句,则编译将该函数视同普

18、通函数那样产生函数调用代码,递归函数(自己调用自己的函数)是不能被用来做内联函数的。内联函数只适合于只有15行的小函数。对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,所以也没有必要用内联函数实现。2.内联函数的定义必须出现在内联函数第一次被调用之前。3.本栏目讲到的类结构中所有在类说明内部定义的函数是内联函数。 23. Const成员函数 const 成员函数可以被相同参数表的非 const 成员函数重载。在这种情况下,类对象的常量性决定了调用哪个函数。构造函数和析构函数是两个例外,即使构造函数和析构函数不是 const 成员函数,const 对象也可以调用它们。 23.

19、几个实例问题(16):运行如下的C+代码,输出是什么?class Apublic: virtual void Fun(int number = 10) std:cout A:Fun with number number; ; class B: public Apublic: virtual void Fun(int number = 20) std:cout B:Fun with number number; ; int main() B b; A &a = b; a.Fun();答案:输出B:Fun with number 10。由于a是一个指向B实例的引用,因此在运行的时候会调用B:Fun

20、。但缺省参数是在编译期决定的。在编译的时候,编译器只知道a是一个类型a的引用,具体指向什么类型在编译期是不能确定的,因此会按照A:Fun的声明把缺省参数number设为10。 这一题的关键在于理解确定缺省参数的值是在编译的时候,但确定引用、指针的虚函数调用哪个类型的函数是在运行的时候。问题(17):运行如下的C代码,输出是什么?char* GetString1() char p = Hello World; return p; char* GetString2() char *p = Hello World; return p; int _tmain(int argc, _TCHAR* arg

21、v) printf(GetString1 returns: %s. n, GetString1(); printf(GetString2 returns: %s. n, GetString2(); return 0;答案:输出两行,第一行GetString1 returns: 后面跟的是一串随机的内容,而第二行GetString2 returns: Hello World. 两个函数的区别在于GetString1中是一个数组,而GetString2中是一个指针。当运行到GetString1时,p是一个数组,会开辟一块内存,并拷贝Hello World初始化该数组。接着返回数组的首地址并退出该函

22、数。由于p是GetString1内的一个局部变量,当运行到这个函数外面的时候,这个数组的内存会被释放掉。因此在_tmain函数里再去访问这个数组的内容时,结果是随机的。当运行到GetString2时,p是一个指针,它指向的是字符串常量区的一个常量字符串。该常量字符串是一个全局的,并不会因为退出函数GetString2而被释放掉。因此在_tmain中仍然根据GetString2返回的地址得到字符串Hello World。问题(19):运行下图中C代码,输出的结果是什么?int _tmain(int argc, _TCHAR* argv) char str1 = hello world; char

23、 str2 = hello world; char* str3 = hello world; char* str4 = hello world; if(str1 = str2) printf(str1 and str2 are same.n); else printf(str1 and str2 are not same.n); if(str3 = str4) printf(str3 and str4 are same.n); else printf(str3 and str4 are not same.n); return 0;答案:输出两行。第一行是str1 and str2 are no

24、t same,第二行是str3 and str4 are same。str1和str2是两个字符串数组。我们会为它们分配两个长度为12个字节的空间,并把hello world的内容分别拷贝到数组中去。这是两个初始地址不同的数组,因此比较str1和str2的值,会不相同。str3和str4是两个指针,我们无需为它们分配内存以存储字符串的内容,而只需要把它们指向hello world“在内存中的地址就可以了。由于hello world”是常量字符串,它在内存中只有一个拷贝,因此str3和str4指向的是同一个地址。因此比较str3和str4的值,会是相同的。题目(13):编译运行下图中的C+代码,

25、结果是什么?(A)编译错误;(B)编译成功,运行时程序崩溃;(C)编译运行正常,输出10。请选择正确答案并分析原因。#include class Aprivate: int value; public: A(int n) value = n; A(A other) value = other.value; void Print() std:cout value std:endl; ; int _tmain(int argc, _TCHAR* argv) A a = 10; A b = a; b.Print(); return 0;答案:编译错误。在复制构造函数中传入的参数是A的一个实例。由于是

26、传值,把形参拷贝到实参会调用复制构造函数。因此如果允许复制构造函数传值,那么会形成永无休止的递归并造成栈溢出。因此C+的标准不允许复制构造函数传值参数,而必须是传引用或者常量引用。在Visual Studio和GCC中,都将编译出错。题目(七):运行下列C+代码,输出什么?class Apublic: A() Print(); virtual void Print() printf(A is constructed.n); ; class B: public Apublic: B() Print(); virtual void Print() printf(B is constructed.n

27、); ; int _tmain(int argc, _TCHAR* argv) A* pA = new B(); delete pA; return 0;答案:先后打印出两行:A is constructed. B is constructed. 调用B的构造函数时,先会调用B的基类及A的构造函数。然后在A的构造函数里调用Print。由于此时实例的类型B的部分还没有构造好,本质上它只是A的一个实例,他的虚函数表指针指向的是类型A的虚函数表。因此此时调用的Print是A:Print,而不是B:Print。接着调用类型B的构造函数,并调用Print。此时已经开始构造B,因此此时调用的Print是B

28、:Print。同样是调用虚拟函数Print,我们发现在类型A的构造函数中,调用的是A:Print,在B的构造函数中,调用的是B:Print。因此虚函数在构造函数中,已经失去了虚函数的动态绑定特性。题目(一):我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函数(写在函数的最后表示不能修改成员变量,不是指写在前面表示返回值为常量)。请问:能不能同时用static和const修饰类的成员函数?分析:答案是不可以。C+编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时

29、候,该函数是没有this指针的。也就是说此时static的用法和const是冲突的。我们也可以这样理解:两者的语意是矛盾的。static的作用是表示该函数只作用在类型的静态变量上,与类的实例没有关系;而const的作用是确保函数不能修改类的实例的状态,与类型的静态变量没有关系。因此不能同时用它们。题目(二):运行下面的代码,输出是什么?class A; class Bpublic: B() B() ; class Cpublic: C() virtual C() ; int _tmain(int argc, _TCHAR* argv) printf(%d, %d, %dn, sizeof(A),

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1