《C和C++常见笔试题.doc》由会员分享,可在线阅读,更多相关《C和C++常见笔试题.doc(32页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、1.是不是一个父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,也能实现多态?virtual修饰符会被隐形继承的。private 也被集成,只事派生类没有访问权限而已。virtual可加可不加。子类的空间里有父类的所有变量(static除外)。同一个函数只存在一个实体(inline除外)。子类覆盖它的函数不加virtual ,也能实现多态。在子类的空间里,有父类的私有变量。私有变量不能直接访问。2.输入一个字符串,将其逆序后输出。(使用C+,不建议用伪码)#include using namespace std;void main()char a50;memset(a
2、,0,sizeof(a);int i=0,j;char t;cin.getline(a,50,n);for(i=0,j=strlen(a)-1;istrlen(a)/2;i+,j-) t=ai; ai=aj; aj=t;coutastr;str.replace;couta /= (k+m)*1*(k+m);=a = a/9;=a = 1;是错的SQR(k+m)/SQR(k+m)= k+m*k+m/k+m*k+m正确5.const 符号常量;(1)const char *p(2)char const *p(3)char * const p说明上面三种描述的区别;如果const位于星号的左侧,则c
3、onst就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。(1)const char *p一个指向char类型的const对象指针,p不是常量,我们可以修改p的值,使其指向不同的char,但是不能改变它指向非char对象,如:const char *p;char c1=a;char c2=b;p=&c1;/okp=&c2;/ok*p=c1;/error(3)char * const p此时*p可以修改,而p不能修改。(4)const char * const p这种是地址及指向对象都不能修改。6.下面是C语言中两种if语
4、句判断方式。请问哪种写法更好?为什么?int n;if (n = 10) / 第一种判断方式if (10 = n) / 第二种判断方式如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了=7.下面的代码有什么问题?void DoSomeThing(.)char* p;.p = malloc(1024); / 分配1K的空间if (NULL = p)return;.p = realloc(p, 2048); / 空间不够,重新分配到2Kif (NULL = p)return;.A:p = malloc(1024); 应该写成: p = (char *) malloc(1024)
5、; 没有释放p的空间,造成内存泄漏。8.下面的代码有什么问题?并请给出正确的写法。void DoSomeThing(char* p)char str16;int n;assert(NULL != p);scanf(p, %s%d, str, n);if (0 = strcmp(str, something).A:sscanf(p, %s%d, str, n); 这句该写成: sscanf(p, %s%d, str, &n);9.下面代码有什么错误?Void test1() char string10; char *str1=;strcpy(string, str1); 数组越界-10.下面代码
6、有什么问题?Void test2() char string10, str110; for(i=0; i10;i+) str1i =a; strcpy(string, str1); 数组越界11.下面代码有什么问题?Void test3(char* str1) char string10; if(strlen(str1)=10) strcpy(string, str1); =数组越界=strcpy拷贝的结束标志是查找字符串中的0 因此如果字符串中没有遇到0的话 会一直复制,直到遇到0,上面的123都因此产生越界的情况建议使用 strncpy 和 memcpy12.下面代码有什么问题?#defi
7、ne MAX_SRM 256 DSN get_SRM_no() static int SRM_no; /是不是这里没赋初值?int I; for(I=0;I=MAX_SRM) return (NULL_SRM); else return SRM_no; 系统会初始化static int变量为0,但该值会一直保存,所谓的不可重入.13.写出运行结果:/ test1 char str = world; cout sizeof(str) : ; char *p = str; cout sizeof(p) : ; char i = 10; cout sizeof(i) : ; void *pp = m
8、alloc(10); cout sizeof(p) endl;6:4:1:414.写出运行结果:/ test2 union V struct X unsigned char s1:2; unsigned char s2:3; unsigned char s3:3; x;unsigned char c; v; v.c = 100; printf(%d, v.x.s3); 315.用C+写个程序,如何判断一个操作系统是16位还是32位的?不能用sizeof()函数A1:16位的系统下,int i = 65536;cout i; / 输出0;int i = 65535;cout i; / 输出-1;
9、32位的系统下,int i = 65536;cout i; / 输出65536;int i = 65535;cout 65536 ) cout32 bitendl;else cout16 bitendl;16.C和C+有什么不同?从机制上:c是面向过程的(但c也可以编写面向对象的程序);c+是面向对象的,提供了类。但是,c+编写面向对象的程序比c容易从适用的方向:c适合要求代码体积小的,效率高的场合,如嵌入式;c+适合更上层的,复杂的; llinux核心大部分是c写的,因为它是系统软件,效率要求极高。从名称上也可以看出,c+比c多了+,说明c+是c的超集;那为什么不叫c+而叫c+呢,是因为c+
10、比c来说扩充的东西太多了,所以就在c后面放上两个+;于是就成了c+C语言是结构化编程语言,C+是面向对象编程语言。C+侧重于对象而不是过程,侧重于类的设计而不是逻辑的设计。17.在不用第三方参数的情况下,交换两个参数的值#include void main() int i=60; int j=50; i=i+j; j=i-j; i=i-j; printf(i=%dn,i); printf(j=%dn,j);方法二:i=j;j=i;i=j;方法三:/ 用加减实现,而且不会溢出a = a+b-(b=a)18.有关位域的面试题(为什么输出的是一个奇怪的字符)a.t = b;效果相当于 a.t= b
11、& 0xf;b - b & 0xf -所以输出Ascii码为2的特殊字符char t:4;就是4bit的字符变量,同样unsigned short i:8;就是8bit的无符号短整形变量19.int i=10, j=10, k=3; k*=i+j; k最后的值是?6020.进程间通信的方式有?进程间通信的方式有 共享内存, 管道 ,Socket ,消息队列 , DDE等21.struct A char t:4; char k:4; unsigned short i:8; unsigned long m; ; sizeof(A)=?(不考虑边界对齐)8struct CELL / Declare
12、CELL bit field unsigned character : 8; / ? unsigned foreground : 3; / 00000? unsigned intensity : 1; / 0000?000 unsigned background : 3; / 0?0000 unsigned blink : 1; / ? screen2580; / Array of bit fields二、位结构 位结构是一种特殊的结构, 在需按位访问一个字节或字的多个位时, 位结构 比按位运算符更加方便。 位结构定义的一般形式为: struct位结构名 数据类型 变量名: 整型常数; 数据类
13、型 变量名: 整型常数; 位结构变量; 其中: 数据类型必须是int(unsigned或signed)。 整型常数必须是非负的整 数, 范围是015, 表示二进制位的个数, 即表示有多少位。 变量名是选择项, 可以不命名, 这样规定是为了排列需要。 例如: 下面定义了一个位结构。 struct unsigned incon: 8; /*incon占用低字节的07共8位*/ unsigned txcolor: 4;/*txcolor占用高字节的03位共4位*/ unsigned bgcolor: 3;/*bgcolor占用高字节的46位共3位*/ unsigned blink: 1; /*bli
14、nk占用高字节的第7位*/ ch; 位结构成员的访问与结构成员的访问相同。 例如: 访问上例位结构中的bgcolor成员可写成: ch.bgcolor 注意: 1. 位结构中的成员可以定义为unsigned, 也可定义为signed, 但当成员长度为1时, 会被认为是unsigned类型。因为单个位不可能具有符号。 2. 位结构中的成员不能使用数组和指针, 但位结构变量可以是数组和指针, 如果是指针, 其成员访问方式同结构指针。 3. 位结构总长度(位数), 是各个位成员定义的位数之和, 可以超过两个字节。 4. 位结构成员可以与其它结构成员一起使用。 例如: struct info char
15、 name8; int age; struct addr address; float pay; unsigned state: 1; unsigned pay: 1; workers;上例的结构定义了关于一个工人的信息。其中有两个位结构成员, 每个位结构成员只有一位, 因此只占一个字节但保存了两个信息, 该字节中第一位表示工 人的状态, 第二位表示工资是否已发放。由此可见使用位结构可以节省存贮空间。22.下面的函数实现在一个固定的数上加上一个数,有什么错误,改正 int add_n(int n) static int i=100; i+=n; return i; 答:因为static使得i的
16、值会保留上次的值。去掉static就可了23.下面的代码有什么问题?class A public: A() p=this; A() if(p!=NULL) delete p; p=NULL; A* p; ;答:会引起无限递归24.union a int a_int1;double a_double;int a_int2;typedef structa a1;char y; b;class cdouble c_double;b b1;a a2;输出coutsizeof(c)j+) & (i+ = j) i+=j;答:i = 526.unsigned short array=1,2,3,4,5,6
17、,7;int i = 3;*(array + i) = ?答:427.class Avirtual void func1();void func2();Class B: class Avoid func1()cout fun1 in class B endl;virtual void func2()cout fun2 in class B endl; A, A中的func1和B中的func2都是虚函数.B, A中的func1和B中的func2都不是虚函数.C, A中的func2是虚函数.,B中的func1不是虚函数.D, A中的func2不是虚函数,B中的func1是虚函数.答:A28.数据库
18、:抽出部门,平均工资,要求按部门的字符串顺序排序,不能含有human resource部门,employee结构如下:employee_id, employee_name, depart_id,depart_name,wage答:select depart_name, avg(wage)from employeewhere depart_name human resourcegroup by depart_nameorder by depart_name29.给定如下SQL数据库:Test(num INT(4) 请用一条SQL语句返回num的最小值,但不许使用统计功能,如MIN,MAX等答:s
19、elect top 1 numfrom Testorder by num desc31.试编写函数判断计算机的字节存储顺序是开序(little endian)还是降序(bigendian)答:bool IsBigendian()unsigned short usData = 0x1122;unsigned char *pucData = (unsigned char*)&usData;return (*pucData = 0x22);32.简述Critical Section和Mutex的不同点对几种同步对象的总结1.Critical SectionA.速度快B.不能用于不同进程C.不能进行资
20、源统计(每次只可以有一个线程对共享资源进行存取)2.MutexA.速度慢B.可用于不同进程C.不能进行资源统计3.SemaphoreA.速度慢B.可用于不同进程C.可进行资源统计(可以让一个或超过一个线程对共享资源进行存取)4.EventA.速度慢B.可用于不同进程C.可进行资源统计33.一个数据库中有两个表:一张表为Customer,含字段ID,Name;一张表为Order,含字段ID,CustomerID(连向Customer中ID的外键),Revenue;写出求每个Customer的Revenue总和的SQL语句。建表create table customer(ID int primar
21、y key,Name char(10)gocreate table order(ID int primary key,CustomerID int foreign key references customer(id) , Revenue float)go-查询select Customer.ID, sum( isnull(Order.Revenue,0) )from customer full join order on( order.customerid=customer.id )group by customer.id35.程序改错class mmlprivate: static uns
22、igned int x;public: mml() x+; mml(static unsigned int &) x+; mmlx-;pulic: virtual mon() = 0; static unsigned int mmc()return x; . ;class nnl:public mmlprivate: static unsigned int y;public: nnl() x+; nnl(static unsigned int &) x+; nnlx-;public: virtual mon() ; static unsigned int nnc()return y; . ;代
23、码片断:mml* pp = new nnl;.delete pp;A:基类的析构函数应该为虚函数virtual mmlx-;36.101个硬币100真、1假,真假区别在于重量。请用无砝码天平称两次给出真币重还是假币重的结论。答:101个先取出2堆,33,33第一次称,如果不相等,说明有一堆重或轻那么把重的那堆拿下来,再放另外35个中的33如果相等,说明假的重,如果不相等,新放上去的还是重的话,说明假的轻(不可能新放上去的轻)第一次称,如果相等的话,这66个肯定都是真的,从这66个中取出35个来,与剩下的没称过的35个比下面就不用说了方法二:第3题也可以拿A(50),B(50)比一下,一样的话拿
24、剩下的一个和真的比一下。如果不一样,就拿其中的一堆。比如A(50)再分成两堆25比一下,一样的话就在B(50)中,不一样就在A(50)中,结合第一次的结果就知道了。37.static变量和static 函数各有什么特点?答:static变量:在程序运行期内一直有效,如果定义在函数外,则在编译单元内可见,如果在函数内,在在定义的block内可见;static函数:在编译单元内可见;38.用C 写一个输入的整数,倒着输出整数的函数,要求用递归方法 ;答:void fun( int a )printf( %d, a%10 );a /= 10;if( a =0 ) return;fun( a );40
25、.int idsizeof(unsigned long); 这个对吗?为什么?答:对。这个 sizeof是编译时运算符,编译时就确定了可以看成和机器有关的常量。求下面函数的返回值( 微软) int func(x) int countx = 0; while(x) countx +; x = x&(x-1); return countx; 假定x = 9999。 答案:8 思路:将x转化为2进制,看含有的1的个数。 2. 什么是“引用”?申明和使用“引用”要注意哪些问题? 答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进
26、行初始化。引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。 3. 将“引用”作为函数参数有哪些特点? (1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。 (2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直
27、接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。 (3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用*指针变量名的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。 4. 在什么时候需要使用“常引用”? 如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数
28、中被改变,就应使用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名; int a ; const int &ra=a; ra=1; /错误 a=1; /正确 string foo( ); void bar(string & s); 那么下面的表达式将是非法的: bar(foo( ); bar(hello world); 原因在于foo( )和hello world串都会产生一个临时对象,而在C+中,这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。 引用型参数应该在能被定义为const的情况下,尽量定义为
29、const 。 5. 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则? 格式:类型标识符 &函数名(形参列表及类型说明) /函数体 好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error! 注意事项: (1)不能返回局部变量的引用。这条可以参照Effective C+1的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了无所指的引用,程序会进入未知状态。 (2)不能返回函数内部new分配的内存的引用。 这条可以参照Effecti
30、ve C+1的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。 (3)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C+1的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性
31、的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。 (4)流操作符重载返回值申明为“引用”的作用: 流操作符,这两个操作符常常希望被连续使用,例如:cout hello endl;因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用操作符。 因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C+
32、语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。 include int &put(int n); 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 ) retur
33、n valsn; else coutsubscript error; return error; (5)在另外的一些操作符中,却千万不能返回引用:+-*/ 四则运算符。它们不能返回引用,Effective C+1的Item23详细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一 个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为(a+b) = (c+d)会永远为true而导致错误。所以可选的只
34、剩下返回一个对象了。 6. “引用”与多态的关系? 引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。 Class A; Class B : Class A.; B b; A & ref = b; 7. “引用”与指针的区别是什么? 指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。此外,就是上面提到的对函数传ref和pointer的区别。 8. 什么时候需要“引用”? 流操作符、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它
35、情况都推荐使用引用。 以上 2-8 参考 9. 结构与联合有和区别? 1. 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。 2. 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。 10. 下面关于“联合”的题目的输出? a) i nclude union int i; char x2; a; void main() a.x0 = 10; a.x1 = 1; printf(%d,a.i); 答案:266
36、 (低位低地址,高位高地址,内存占用情况是Ox010A) b) main() union /*定义一个联合*/ int i; struct /*在联合中定义一个结构*/ char first; char second; half; number; number.i=0x4241; /*联合成员赋值*/ printf(%c%cn, number.half.first, mumber.half.second); number.half.first=a; /*联合中结构成员赋值*/ number.half.second=b; printf(%xn, number.i); getch(); 答案: A
37、B (0x41对应A,是低位;Ox42对应B,是高位) 6261 (number.i和number.half共用一块地址空间) 11. 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中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) ; return tempptr ; 12. 已知String类定义如下: class Stri
限制150内