1)下列代码编译时会产生错误的是()
- #include <iostream>
- using namespace std;
- struct Foo
- {
- Foo() { }
- Foo(int) { }
- void fun() { }
- };
- int main(void)
- {
- Foo a(10); //语句1
- a.fun(); //语句2
- Foo b(); //语句3
- b.fun(); //语句4
- return 0;
- }
A、语句1 B、语句2 C、语句3 D、语句4
说明:诈一看,是语句3报错,因为调用缺省构造函数是不需要写括号的,但事实上语句4报错。语句3其实是编译通过的,只不过被编译器理解为一个没有参数返回一个FOO 类型对象的函数.
(2)在排序方法中,元素比较次数与元素的初始排列无关的是()
A、Shell 排序 B、归并排序 C、直接插入排序 D、选择排序
说明:A、C肯定不选的,归并排序的在merge中是跟序列有关,如果有序,比较次数最少n/2,最糟是元素错落n-1。而选择排序比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2。所以 应该是选择排序!
(3)给你1、2、3 这三个数字 可以使用C的各种运算符 你能表示的最大的整数是()
A、2*3*sizeof(1) B、3<<(2<<sizeof(1)) C、sizeof(3)<<(sizeof(2)<<(sizeof(1))) D、(unsigned long)(2-3)*1
(4)判断一个单向链表中是否存在环的最佳方法是()
A、两重遍历 B、快慢指针 C、路径记录 D、哈希表辅助
(5)下面代码的输出是多少?
- class A
- {
- public:
- A() { cout<<"A"<<endl; }
- ~A() { cout<<"~A"<<endl; }
- };
- class B:public A
- {
- public:
- B(A &a):_a(a)
- {
- cout<<"B"<<endl;
- }
- ~B()
- {
- cout<<"~B"<<endl;
- }
- private:
- A _a;
- };
- int main(void)
- {
- A a; //很简单,定义a的时候调用了一次构造函数
- B b(a); //这里b里面的_a是通过成员初始化列表构造起来的
- //而且是通过copy constructor构造的是b的成员对象_a的,这里是编译器默认的,因此在构造好_a前,先调用基类构造函数
- //然后才是构造自身,顺序就是A()->_a->B()(局部)
- //因此这里有两个A,一个B
- //在return之前进行析构
- /************************************************************************/
- /*析构是按照定义对象的反顺序来的,而且同一个对象按照构造的反顺序来的,因此这里先
- 析构b然后才是a,那么b的构造顺序是上面的A()->_a->B()(局部),反过来,就是B()(局部)->_a->A()
- 因此得到的就是~B->~A->~A
- 在b之后就是析构a
- 最后结果就是
- ~B->~A->~A->~A*/
- return 0;
- }
(6)判断一包含n个整数a[]中是否存在i、j、k满足a[i] +>
A.O(n^3) B. O(n^2*logn) C. O(n^3) D. O(nlogn)
(7)下列序排算法中最坏情况下的时间复杂度不是n(n-1)/2的是
A.快速排序 B.冒泡排序 C.直接插入排序 D.堆排序
(8)下列说法错误的是:
A.SATA硬盘的速度大约为500Mbps/s
B.读取18XDVD光盘数据的速度为1Gbps
C.千兆以太网的数据读取速度为1Gpbs
D.读取DDR3内存数据的速度为100Gbps
分析:A和B相比,怎么光盘的速度比硬盘还快?B必错无疑啊。千兆以太网的速度是1000Mbps,也可以写成1Gbps。DDR3-1600的极限传输速度是12.8GBp/s
(9)设在内存中有P1,P2,P3三道程序,并按照P1,P2,P3的优先级次序运行,其中内部计算和IO操作时间由下表给出(CPU计算和IO资源都只能同时由一个程序占用):
P1:计算60ms---》IO 80ms---》计算20ms
P2:计算120ms---》IO 40ms---》计算40ms
P3:计算40ms---》IO 80ms---》计算40ms
完成三道程序比单道运行节省的时间是()
A.80ms
B.120ms
C.160ms
D.200ms
(10)长为n的字符串中匹配长度为m的子串的复杂度为()
A.O(N)
B.O(M+N)
C.O(N+logM)
D.O(M+logN)
(11)发射三次炮弹,射中目标的概率是0.95,请问发射一次能击中目标的概率是多少?
A.0.63
B.0.50
C.0.32
D.0.86
(12)在c++程序中,如果一个整型变量频繁使用,最好将他定义为()
A.auto
B.extern
C.static
D.register
(13)两个等价线程并发的执行下列程序,a为全局变量,初始为0,假设printf、++、--操作都是原子性的,则输出不可能是()
- void foo() {
- if(a <= 0) {
- a++;
- }
- else{
- a--;
- }
- printf("%d", a);
- }
A.01
B.10
C.12
D.22
注:这道题怎么做的
(13)有N个人,其中一个明星和n-1个群众,群众都认识明星,明星不认识任何群众,群众和群众之间的认识关系不知道,现在如果你是机器人R2T2,你每次问一个人是否认识另外一个人的代价为O(1),试设计一种算法找出明星,并给出时间复杂度(没有复杂度不得分)。
遍历 1~n 这n个人;
首先取出 1号 和 2号,
如果 1 认识 2, 那么把 1 去掉;
如果1不认识2,就可以把2去掉了。
每次比较都去掉一个,如此循环;n-1次之后只有一个人了
时间复杂度: O(n-1)
(14)下列程序输出的结果:
- #include<stdio.h>
- int main(void)
- {
- int a=10,b=20,c=30;
- printf("\n%d..%d..%d",a+b+c,b *=2, c*=2);
- return 0;
- }
答案:110..40..60
思路:因为C语言中函数参数默认是从右往左处理,而输出是从左往右
(15)循环移位的构造
- b=a<<(16-n);
- c=a>>n;
- c=c|b;
(16)谈谈如下两式的含义以及区别(C陷阱与缺陷15~19页):
float *g();//因为()的结合优先级比*高,所以该表达式相当于float *(g()),即g是一个函数,函数的返回值为float类型的指针,这是一个函数的声明。
float (*h)();//h先和*结合,表示h是一个指针,再和()结合表示一个函数。即表示h是一个函数指针,该函数返回值为浮点类型。
(float (*)());//表示一个“指向返回值为浮点类型的函数的指针”的类型转换符。
(void (*)())0;//表示将0转换为“返回值为void类型的函数的指针”类型。
(*(void (*)())0)();//调用上面这个指针的函数。
typedef void(*funcptr)();//funcptr就可以用了定义变量,定义变量类型为返回值为void类型的函数指针。
(*(funcptr)0)();//首先将0转换为funcptr类型的函数指针,然后调用相应的函数。
void (*signal(int,void(*)(int)))(int);//首先看涂黑的地方,这是一个函数,其返回类型为一个指针。函数参数为int和一个指向“参数为int,返回类型为void”的指针。再拼起来,该语句声明了一个函数signal,其返回类型函数指针看红色的地方,即返回值为void(*)int。可以通过如下的方式来简化操作:
typedef void(*HANDLER)(int);
HANDLER signal(int,HANDLER);
int(*(*F)(int,int))(int):根据上面的分析,我们就可以轻而易举的得到(*F)(int,int)为函数指针,而返回类型为int(*)(int)的函数指针。
注:一个函数返回一个函数指针时这么写的: void (*signal(int,void(*)(int)))(int);
注:若fp是一个函数指针,则调用函数有两种方式:(*fp)()以及简写的fp()。
(17)下列的语句错在哪,并改正。(C陷阱与缺陷)
while(c=getc(in)!=EOF){
putc(c,out);
}
问题出现在优先级上,我将优先级从高到低总结为括号->取地址->单目运算->乘除加减移位比较->位与短路选择赋值->逗号。按照这个顺序赋值运算符比比较运算的优先级低,所以上式等价于这样c=(getc(in)!=EOF),这显然是不对的,与设计者的本意不符,改为:
while((c=getc(in))!=EOF){//加一个括号
putc(c,out);
}
(18)下列程序会出现在哪一行崩溃?(程序员面试宝典P71)
- struct S{
- int i;
- int *p;
- };
- int main()
- {
- S s;
- int *p=&s.i;
- p[0]=4;
- p[1]=3;
- s.p=p;
- s.p[1]=1;
- s.p[0]=2;
- }
我觉得指针变化是上面这样一个过程,最终s.p[1]和s.p其实是同一个地方,s.p[1]=1 表示让S.p指向地址为1的地方,s.p[0]=2,就是将地址为1的地方赋值为2,即*((int*)1)=2,出现程序崩溃。
注:(1)int *p,则p+1=p+sizeof(int)*1;
char *p,则p+1=p+sizeof(char)*1;
int *p,int p1 = (char*)p,则p+1=p+sizeof(char)*1
(2)struct 存储为连续存储(不谈对界问题)。
(19)指出下面程序使用错误的地方改正(程序员面试宝典P72)
- int max(int x,int y)
- {return x>y?x:y;}
- int main()
- {
- int *p=&max;
- ...
- }
注:这个地方用int (*p)(int,int)=max也是可以的,因为函数名被使用时总是由编译器把他转换为函数指针。
(20) 某计算机有64位虚地址空间,页大小是2048B.每个页表项长为4B。因为所有页表都必须包含在一页中,故使用多级页表,问一共需要多少级?
2048B=2^11
64-11=53(地址中扣除页内地址位数) 共有2^53页
一页中可以装2048/4=2^9个页表项
9*6>53 至少需要6级页表
//csdn博客目前暂时不再更新了,有兴趣请访问我的技术博客-晓的博客:zhangxiaolong.org