西山居笔试题
一、填空:
1、 char szTest[]=“12345\\t\\n\\0abcd\\0”,求strlen[szText] = 7, sizeof[szTest] = 14.
strlen 是函数,运行时才能确定,所以它只计算了12345\\t\\n 而sizeof 是操作符,它包括所有的字符12345\\t\\n\\0abcd\\0,还要加一个结束字符,所以为13=1 = 14
2、 Int anTest[5][10]; int n1=&anTest[4]-&anTest[0], n2=&anTest[3][1]-&anTest[1][3]; 则n1=____4___ ,n2= ______18____ ;
注意计算第一个的时候可以想一下 指向数组的指针,当指针 +1 的时候实际上是加了一个数组长度,这个题反过来想比较好做
3、 Char szNum[]=”123456789”, int n=*(short*)(szNum+4)- *(short*)(szNum); 则n= ___1028_____ ; 这里(short*)(szNum)是指向12 为内存单元为0000 0001 0000 0010 即两个内存单元存储一个数,(short*)(szNum+4)是指向56,内存中存放为 0000 0101 0000 0110 即两个内存单元存储一个数
4、 Stl 中二分查找法的函数名,稳定排序的函数名,部分排序的函数名各是什么 5、 Stl中的map常用数据结构中的_____红黑树________实现。 6、 比较两数大小,返回较大值 Int cmp(int x,int y){
Return _____a>b? a:b________________; }
7、#include
For(;i<4;)
Std::cout< Int main(){ Cc(1); Return 0; } 请输出结果:4444444 8、要增加一个类到某种类型的隐式转换可通过重载______赋值 操作符实现 9、C++64位编译环境下,sizeof(int)=___4_____,sizeof[int *]=____8______ 自己对于64位平台上各种数据类型分别占用多少字节,存在一些疑问,所以用C/C++中的sizeof分别在这两种平台上进行了测试。 运行结果如下:(分别用蓝色和红色标记了两者的差异) —————————————————————————— 机器平台:X86_64 处理器 操作系统:Red Hat 4.1.2-14 编译器: gcc version 4.1.2 20070626 Size of char is: 1 Size of unsigned char is: 1 Size of signed char is: 1 Size of int is: 4 Size of short is: 2 Size of long is: 8 Size of long int is: 8 Size of signed int is: 4 Size of unsigned int is: 4 Size of unsigned long int is: 8 Size of long long int is: 8 Size of unsigned long long is: 8 Size of float is: 4 Size of double is: 8 Size of long double is: 16 Size of (void *) is: 8 Size of (char *) is: 8 Size of (int *) is: 8 Size of (long *) is: 8 Size of (long long *) is: 8 Size of (float *) is: 8 Size of (double *) is: 8 —————————————————————————— 机器平台: X86_32 处理器 操作系统: Windows XP SP2 编译器: VS2005自带的C++编译器 Size of char is: 1 Size of unsigned char is: 1 Size of signed char is: 1 Size of int is: 4 Size of short is: 2 Size of long is: 4 Size of long int is: 4 Size of signed int is: 4 Size of unsigned int is: 4 Size of unsigned long int is: 4 Size of long long int is: 8 Size of unsigned long long is: 8 Size of float is: 4 Size of double is: 8 Size of long double is: 8 Size of (void *) is: 4 Size of (char *) is: 4 Size of (int *) is: 4 Size of (long *) is: 4 Size of (long long *) is: 4 Size of (float *) is: 4 Size of (double *) is: 4 其实就是所有的指针扩充为8位,long 变为8位, long doulbe 变为16位,注意double 是没有变化的 10、列举c++0x的任意三个新特性 11、unsigned int strilen(const char*pstr) { _asm{ Mov eax,pstr Cmp byte ptr[eax],0 Jz zreturn Zloop: ________________ Cmp byte prt[eax],0 Jnz zloop Zreturn: Sub eax,pstr } } 二、诊断题。若错误,请写出错在哪里 1、 全局变量与静态变量在内在中的存储位置是相同的。 正确。 1。全局变量中static全局变量和普通全局变量的区别: 相同点:1)共存于同一块内存(静态存储区)中; 2)生命期相同,都是到整个程序的生命期; 不同点:1)前者是内部连接,后者是外部连接; 2)作用域不同: 前者的作用域是局部于它所在的文件的,也就是说在当前程序中其它文件中是不能使用它的,如果想在想其它文件中声明它为extern的来访问它,编译器就会报错,当然在其它文件中即使有同名的变量也不会有名字冲突的问题; 后者的作用域是整个程序中的所有文件,可以在其它文件中声明它为extern来访问它,当然在整个程序中不论是否是同一个文件都不能有同名的普通全局变量,否则会有名字冲突,(如果在一个函数体内有与全局变量同名的局部变量,那么局部变量会屏蔽全局变量,除非使用作用域运算符:: ); 2。局部变量中的static变量和普通变更的区别: 相同点:作用域相同,都是局部于当前所在的函数体内。 不同点:1)前者是内部连接,后者没有连接,因为普通局部变量是位于堆栈中,连接器不知道它们; 2)存储区域不同:前者存放于静态存储区,后者存放于栈中; 3)生命期不同:前者是整个程序的生命期,后者是所在函数的生命期(即随它所在的函数调用的结束而结束; 4)初始化:前者只在函数第一次被调用时初始化,当次调用时的变量值会保存到下次调用时使用,也就只初始化一次;后者则是在每次调用函数时都要重新创建它的存储空间,重新初始化一次,即调用一次函数初始化一次。 2、 Windows操作系统中进程是基本执行单位。 答:错,在Windows 中,线程是基本执行单位,进程是一个容纳线程的容器。进程是线程的资源分配单元 3、 在栈上分配内存和在堆上分配内存,效率是一样的 答:堆的效率要低,堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.但是堆的优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。 4、 Sizeof属于C++内置函数 答:错误sizeof()是一个操作符,不是函数,所以在第一题中sizeof的值是14,因为它不是运行时确定 5、 构造函数只能定义为public,不能为protected或private. 答:错误,如果你不想让外面的用户直接构造一个类(假设这个类的名字为A)的对象,而希望用户只能构造这个类A的 子类,那你就可以将类A的构造函数/析构函数声明为protected,而将类A的子类的构造函数/析构函数声明为public。 如果将构造函数/析构函数声明为private,那只能这个类的“内部”的函数才能构造这个类的对象了。这里所说的“内部”是指类的成员函数。 因为在外部不能定义对象,所以不能通过对象调用成员函数,如果想要调用成员函数的话,可以将成员函数定义为静态,然后通过类的::操作符调用,A& ra = A::Instance();ra.Print();即可 6、 C的qsort与C++的std::sort均采用快速排序,但C效率高于C++,故qsort的效率高 答:错,与编译系统有关 7、 用new[]分配的内存如果用delete释放,结果是一定会内存泄露。 答:错误,在林锐的《C++高质量编程》中提到 如果用new 创建对象数组,那么只能使用对象的无参数构造函数。例如 Obj *objects = new Obj[100]; // 创建100 个动态对象 不能写成Obj *objects = new Obj[100](1);// 创建100 个动态对象的同时赋初值1 在用delete 释放对象数组时,留意不要丢了符号‘[]’。例如 delete []objects; // 正确的用法 delete objects; // 错误的用法 后者相当于delete objects[0],漏掉了另外99 个对象。 而如果我们只是 int *p = new int[1]; 则用deledte删除的时候就可以释放p指向的内存,不会造成内存泄露 8、 全局对象及静态对象均在main函数执行之前构造。 对 三、1、unresolved extrenal Symbol是什么错误?原因是什么? 不确定的外部“符号”, 产生这个错误的原因:如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或标签,将产生此错误消息。一般来说,发生错误的原因有两个:一是所引用的函数、变量不存在、拼写不正确或者使用错误;其次可能使用了不同版本的连接库。 2、线程死锁发生的原因?要防止死锁在多线程编程中我们要注意什么? 3、什么叫哈希算法?有什么应用? 4、列举Windows中进程注入的方式。 为了对内存中的某个进程进行操作,并且获得该进程地址空间里的数据,或者修改进程的私有数据结构,必须将自己的代码放在目标进程的地址空间里运行,这时就避免不了使用进程注入方法了。 进程注入的方法分类如下: 带DLL的注入 利用注册表注入 利用Windows Hooks注入 利用远程线程注入 利用特洛伊DLL注入 不带DLL的注入 直接将代码写入目标进程,并启动远程线程 5、请从程序机制上解释缓冲区溢出攻击原理。 当一个超长的数据进入到缓冲区时,超出部分就会被写入其他缓冲区,其他缓冲区存放的可能是数据、下一条指令的指针,或者是其他程序的输出内容,这些内容都被覆盖或者破坏掉。可见一小部分数据或者一套指令的溢出就可能导致一个程序或者*作系统崩溃。 缓冲区溢出是目前导致“黑客”型病毒横行的主要原因。从红色代码到Slammer,再到日前爆发的“冲击波”,都是利用缓冲区溢出漏洞的典型。缓冲区溢出是一个编程问题,防止利用缓冲区溢出发起的攻击,关键在于程序开发者在开发程序时仔细检查溢出情况,不允许数据溢出缓冲区。此外,用户需要经常登录*作系统和应用程序提供商的网站,跟踪公布的系统漏洞,及时下载补丁程序,弥补系统漏洞 6、简述copy-on-write机制及应用。 简单来说,在复制一个对象时并不是真的在内存中把原来对象的数据复制一份到另外一个地址,而是在新对象的内存映射表中指向同原对象相同的位置,并且把那块内存的 Copy-On-Write 位设为 1。在对这个对象执行读操作的时候,内存数据没有变动,直接执行就可以。在写的时候,才真正将原始对象复制一份到新的地址,修改新对象的内存映射表到这个新的位置,然后往这里写。 这个技术需要跟虚拟内存和分页同时使用,其好处是在复制对象的时候因为并不是真的复制,而只是建了一个“指针”,因而大大提高性能。但这并不是一直成立的,前提是在复制新对象之后,进行的写操作只是在一小部分的内存分页上,大部分分页不会用到或者只是读取。不然会产生大量的分页错误,得不偿失。 作用是提高内存的使用率和共享率,在线程同步,迟缓写入等方面都有应用 7、解释函数声明中三个const作用。 Template 1、以下函数把传入的两个整数值存到一个Buffer里,完成函数实现。 Bool StroredDataToBuffer(int a,int b,char *pBuffer,unsigned int uBufferSize); 2、100个苹果完全随机分给4人,每人可能得0~100个。设计一个随机分配算法。要求:在结果随机(不可预知)基础上每种分配概率均等。如(25,25,25,25),(0,0,0,100)都是分配结果,机率一样。 3、某游戏服务器最多能同时接受N个连接,当游戏客户端连接服务器时,服务器会给该连接分配一个连接ID(ID范围1~N),当游戏客户端断开连接时该ID会重新回收重用,请设计并实现一个ID分配器,说明:1)ID分配给一个连接后回收前不能再分配。 2)若已无可分配ID,则分配失败,返回0