1. Which of the following calling convention(s) support(s) supportvariable-length parameter(e.g. printf)?(3 Points)
A. cdecl
B. stdcall
C. pascal
D. fastcall
问题解析:本题要求选出像printf一样支持变长参数的函数调用约定。
1.什么是函数调用约定?
答:当一个函数被调用时,函数的参数会被传递给被调用的函数,同时函数的返回值会被返回给调用函数。函数的调用约定就是用来描述参数(返回值)是怎么传递并且由谁来平衡堆栈的。
2.常见的函数调用约定有哪些?
答:__stdcall,__cdecl,__fastcall,__thiscall,__nakedcall,__pascal
按参数的传递顺序对这些约定可划分为:
a).从右到左依次入栈:__stdcall,__cdecl,__thiscall
b).从左到右依次入栈:__pascal,__fastcall
3.支持变长的函数调用约定有哪些?
答:__cdecl,带有变长参数的函数必须是cdecl调用约定,由函数的调用者来清除栈,参数入栈的顺序是从右到左
2. What's the output of the following code?(3 Points)
#include<iostream> using namespace std; class A { public: virtual void f() { cout<<"A::f()"; } void f() const { cout<<"A::f() const"<<endl; } }; class B: public A { public: void f() { cout<<"B::f()"; } void f() const { cout<<"B::f() const"<<endl; } }; void g(const A* a) { a->f(); } int main() { A* a = new B(); a->f(); g(a); delete a ; return 0; }
A. B::f()B::f()const
B. B::f()A::f()const
C. A::f()B::f()const
D. A::f()A::f()const
问题解析:本题主要考察C++的重载与多态。
1.C++的多态性是如何体现的?
答: 在C++中,多态性仅用于通过继承而相关联的类型的引用或指针。
- 通过继承我们能够定义这样的类,它们对类型之间的关系建模,共享公共的东西,仅仅特化本质上不同的东西。派生类能够继承基类定义的成员;派生类可以无需改变而使用那些鱼派生类型具体不相关的操作;派生类可以重定义那些与派生类型相关的成员函数,将函数特化,考虑派生类型的特性;最后,除了从基类继承的成员之外,派生类还可以定义更多的成员。
在C++中,基类必须指出希望派生类重定义哪些函数,定义为virtual的函数是基类期待派生类重新定义的,基类希望派生类继承的函数不能定义为虚函数。
- 通过动态绑定我们能够编写程序使用继承层次中任意类型的对象,无需关心对象的具体类型。使用这些类的程序无需区分函数是在积累还是在派生类中定义的。
在C++中,通过基类的引用(或指针)调用虚函数时,发生动态绑定。引用(或指针)既可以指向基类对象也可以指向派生类对象,这一事实是动态绑定的关键。用引用(或)指针调用的虚函数在运行时确定,被调用的函数是引用(或指针)所指对象的实际类型所定义的。
本例中代码同动态绑定相关联的代码为:
A* a = new B(); a->f();
基类A将函数void f()定义为virtual类型,A的派生类B重新定义void f()函数,这一点主要应用了继承这一特性。
在main()函数中,定义一个A类型的指针a,将其指向派生类B,然后调用a->f()实质上应用的就是动态绑定了,即“用引用(或)指针调用的虚函数在运行时确定,被调用的函数是引用(或指针)所指对象的实际类型所定义的”,故第一次输出为:B::f()。
此外,C++中的函数调用默认不使用动态绑定。要触发动态绑定,必须满足两个条件:第一,只有指定为虚函数的成员函数才能进行动态绑定,成员函数默认为非虚函数,非虚函数不进行动态绑定;第二,必须通过基类类型的引用或指针进行函数调用。
2.重载函数
定义:出现在相同的作用域中的两个函数,如果具有相同的名字而形参表不用,则成为函数重载。注意函数重载不能基于不同的返回值类型进行重载。同时注意函数重载中的“形参表”不同,是指本质不同,不要被一些表象迷惑。main函数不能被重载。本例中的基类A和派生类都存在着重载,以基类A为例进行说明:
class A { public: virtual void f() { cout<<"A::f()"; } void f() const { cout<<"A::f() const"<<endl; } };
从代码中可以看到在A类中,f()函数是发生重载了,而且是合法的。在调用时,只用A类的const对象才能调用const版本的f函数,而非const对象可以调用任意一种,通常非const对象调用不是const版本的f()函数。
是不是感到很困惑了,按照重载函数的定义知不同返回值类型的函数不能进行重载,这里为什么又是重载呢?
这里可以重载的原因是:按照函数重载的定义,函数名相同而形参表有本质不同的函数称为重载。在类中,由于隐含的this形参的存在,const版本的f()函数使得作为形参的this指针的类型变为指向const对象的指针,而非const版本的使得作为形参的this指针就是正常版本的指针。此处是发生重载的本质。重载函数在最佳匹配过程中,对于const对象调用的就选取const版本的成员函数,而普通的对象调用就选取非const版本的成员函数。
(注:this指针是一个const指针,地址不能改,但能改变其指向的对象或者变量)
解答:首先,两个成员函数如果只是常量性不同,可以被重载。
先看main函数中的a->f(),由于a不是常量的指针,所以编译器首先匹配到的是void f(),由于此函数是虚函数,因此实行动态绑定,因为a所指的实际类型是class B,所以执行过程中实际调用的是void B::f()。
函数g中的调用,因为参数a是const A*,所以a->f()匹配的是void f() const,由于该函数不是虚函数,因此执行静态绑定,a所指的静态类型是class A,所以执行的是void A::f() const。
3. What is the d
3. What is the difference between a linked list and an array?(3 Points)
A. Search complexity when both are sorted
B. Dynamically add/remove
C. Random access efficiency
D. Data storage type
问题解析:本题考查基本的数据结构内容,比较链表和数组的区别。下面从逻辑结构和内存存储 两个方面进行详细的描述:
- 从逻辑结构来看
- 数组必须事先定义固定的长度,即元素的个数,不能适应数据的动态增减;
- 链表动态地分配存储空间,可以适应数据动态的增减。
这种逻辑结构导致的结果:
1)随机访问效率不同:数组可以根据下标直接存取数据,实现高效的随机访问,而链表必须通过遍历节点才能取得数据。
2)数据基本有序的情况下查找数据的时间效率也不同:在数据基本有序的情况下访问数组可以利用折半查找方法先确定下标,然后通过下标快速得到数据,而链表则需要遍历整个表才能得到数据;
3)动态插入和删除的效率不同:数组中插入、删除数据项时,需要移动其他数据项,非常繁琐;而链表可以根据next指针找到下一个元素,实现动态的插入和删除效率较高。
- 从内存存储来看
- (静态)数组从栈中分配空间,自由度小,并且数组的各个元素之间的物理位置是相邻的。
- 链表从堆中分配空间,自由度大,链表中各个节点的物理位置可以不是相邻的。
4. About the Thread and Process in Windows, which description(s) is(are) correct:(3 Points)
A. One application in OS must have one Process, but not a necessary to have one Thread
B. The Process could have its own Stack but the thread only could share the Stack of its parent Process
C. Thread must belongs to a Process
D. Thread could change its belonging Process
问题分析:见http://www.cnblogs.com/pangblog/archive/2013/08/19/3268790.html
解答:此题考察进程与线程的概念。
进程是系统进行资源分配的基本单位,有独立的内存地址空间;线程是CPU调度的基本单位,没有单独地址空间,有独立的栈、局部变量、寄存器、程序计数器等。
创建进程的开销大,包括创建虚拟地址空间等需要大量系统资源;创建线程开销小,基本上只有一个内核对象和一个堆栈。
进程切换开销大,线程切换开销小。进程间通信开销大,线程间通信开销小。
线程属于进程,不能独立执行。每个进程至少有一个线程,成为主线程。
5. What is the output of the following code?(3 Points)
{ int x = 10 ; int y = 10 ; x = x++ ; y = ++y ; printf("%d, %d ",x,y); }
问题解析:本题主要考察队编程语言的基本语法的理解。
在C语言和C++语言中,自增运算符的使用可以是程序看着简洁,思路也比较清晰。自增运算符又分为前自增和后自增两类,即定义一个变量,如int i=10;
前自增可以表示为:++i;
后自增可以表示为:i++;
单纯的看这两条语句,在执行完毕之后i值并没有太大的区别,均为11。下面来点不同的:
int i = 10, j = 10; int x, y; x = i++; y = ++j;
问x和y值是否相等?结论是x=10,y=11,所以他们不等。语句x = i++;的执行流程是先将i值赋给x(x=10),然后i值再加1(i=11)。而语句y = ++j;的流程则是j先加1(j=11),然后再将j值赋给y(y=j=11)。所以本题答案为D选项。
另外,做一些关于java语言处理前自增和后自增的补充说明。java语言中
int i = 10; i = i++; system.out.println(i);
执行如上代码输出结果为10,所以很多同学认为选项B也是正确的,但这里注意题目中输出语句采用的是printf()函数,故可以理解为C语言代码或C++代码,所以本题的唯一解为选项D。
解答:前置++与后置++。这个问题不同编译器表现的结果常常有差异,特别是多余连续多个出现在同一个语句中时。这里以VS2010的处理方式为例,不保证其他编译器下能得到相同结果。
++i表示,i自增1后再参与其它运算;而i++ 则是i参与运算后,i的值再自增1。自减运算符--与之类似。
语句x = x++; VS2010将其处理成x = x; x = x+1; 对应的汇编代码为:
mov eax,dword ptr [x]
mov dword ptr [x],eax
mov ecx,dword ptr [x]
add ecx,1
mov dword ptr [x],ecx
语句y = ++y; VS2010将其处理成y = y+1; y = y; 对应的汇编代码为:
mov eax,dword ptr [y]
add eax,1
mov dword ptr [y],eax
mov ecx,dword ptr [y]
mov dword ptr [y],ecx
所以结果是11, 11。
下面看一下以下两个语句:
int a = (x++)+(x++);
int b = (++y)+(++y);
按照上面的方式,可以解释成:
int a = x + x;
x = x + 1;
x = x + 1;
y = y + 1;
y = y + 1;
int b = y + y;
最后a = 20,y = 24(VS2010结果)。
6. For the following Java or C# code(3 Points)
int [][] myArray3 = new int[3][]{ new int[3]{5,6,2}, new int[5]{6,9,7,8,3}, new int[2]{3,2}};
What will myArray3[2][2] returns?
A. 9
B. 2
C. 6
D. overflow
问题解析:本题考查的是基本的语法知识。无论是Java语言还是C#语言,在计算机的基本语法中,数组始终是以0开始,对于一个具有n个元素的一位数组,其下标是从0到n-1。因此本例中定义的二维数组myArray3[][],第一个元素对应的下标表示为myArray3[0][0],问题中的myArray3[2][2]理解为第三行第三个元素,查找原始数据发现,第三行仅包含两个元素,超出了数组可访问的位置,发生溢出。
7. Please choose the right statement about const usage:(3 Points)
A. const int a; //const integer
B. int const a; //const integer
C. int const *a; //a pointer which point to const integer
D. const int *a; //a const pointer which point to integer
E. int const *a; // a const pointer which point to integer
问题解析:本题考查C++中用const限定符和指针来修饰对象时,对象的属性问题。
- const限定符可以将一个对象转换成一个常量。注意因为用const限定符定义的常量在定义后就不能被修改,所以定义时必须初始化。
- 指向const对象的指针,C++语言强制要求指向const对象的指针也必须具有const特性。如本题中const int *a;这里的a是一个指向int类型的const对象指针,const限定了a指针所指向的对象类型,而并非a本身,即a本身并不是const类型。同时把一个const对象的地址赋给一个普通的、非const对象的指针也会导致编译时错误。
const int r = 2; const int *a = 1; //(1) a++; //correct *a++; //error:*a might be const //(2) const int *cptr = &r; //correct: cptr is a pointer to const int *ptr = &r; //error: ptr is a plain pointer //(3) const void *vp = &r; //correct,vp is const void *pv = &r; //error:r is const
3.const指针:除指向const对象的指针外,C++语言还提供了const指针——本身的值不能修改。
int errNumb = 0; int *const curErr = &errNumb; //curErr is a constant pointer
我们可以将curErr读作“指向int型对象的const指针”。即curErr不能指向其他对象,任何企图给const指针赋值的行为都会导致编译时的错误。另外,const指针必须在定义时初始化。
4.如何识别const指针和指向const对象的指针?const限定符既可以放在类型前也可以放在类型后,但对于非指针类型的const限定符,放在类型前和类型后效果相同。对于既有const限定符又有指针的情况下,我们可以比较*和const的位置来判断他们属于那种类型。const在*之前则为指向const对象的指针,const在*之后则为const指针。
8. Given the following code:(3 Points)
#include <iostream> class A{ public: long a; }; class B : public A { public: long b; }; void seta(A* data, int idx) { data[idx].a = 2; } int _tmain(int argc, _TCHAR *argv[]) { B data[4]; for(int i=0; i<4; ++i) { data[i].a = 1; data[i].b = 1; seta(data, i); } for(int i=0; i<4; ++i) { std::cout<<data[i].a<<data[i].b; } return 0; }
What is the correct result?
A. 11111111
B. 12121212
C. 11112222
D. 21212121
问题解析:测试运行结果为——22221111
seta中,参数是基类C类型的指针,然后移动指针取对象并赋值,
但是main中往函数seta中传递的是派生类的对象数组的起始地址。。。
函数seta中,
data[index].a=2;
等价于:(*(data+index)).a=2;
这里的data类型是参数列表中的C*,所以如果传进来的data是派生类对象数组的起始地址,那么指针data+index已经不再指向第index个对象了。
原因是C和D所占内存不同。
自己慢慢体会吧。。。
给的答案里好像没有这个啊??难道这道题目最好的办法就是空着?(你选哪个都会扣分)
解答:此题答案应该是22221111,选项中没有。
首先为了区分,我们重命名如下:
B data[4];
A *pA = (A*)data;
这样上面的函数调用seta就转换为
pA[i] = 2;
通过data[i]和pA[i]操作数据并没有什么关系,不要受B继承自A影响。data和pA只是指向相同的起始地址,但它们对内存的解释方式不同,data[i] = data + i*sizeof(B),pA[i] = pA+i*sizeof(A)。下面看一下内存说明图:
这样执行结果就明晰了。
9. 1 of 1000 bottles of water is poisoned which will kill a rat in 1 week if the rat drunk any amout of the water. Given the bottles of water have no visual difference, how many rats are needed at least to find the poisoned one in 1 week?(5 Points)
A. 9
B. 10
C. 32
D. None of the above
问题解析:本题主要考察二进制与十进制的转换,但更多的需要灵活的思考问题。1000瓶水里只有一瓶有毒,但具体是哪一瓶未知,将这1000瓶水按二进制的方式编号1-1000,即0000000001、0000000010、0000000011、……、1111100111,然后小白鼠10只分别按顺序排列,即小白鼠喝与不喝某瓶水用0和1表示,所以10只小白鼠共能表示1024(210)种状态,1000瓶水按编号来喂小白鼠(如编号为1000110101时,给小白鼠1、3、5、6、10喂水),一周后观察结果,若1、3、5、6、10这几只小白鼠死亡,则代表编号为1000110101的瓶子中的水有毒,同理若1、2、3这三只小白鼠死亡,则代表编号为000000111的水有毒。
(2^n > 1000),n=10即可。
10. Which of the following statement(s) equal(s) value 1 in C programming language?(5 Points)
A. the return value of main function if program ends normally
B. return (7&1)
C. char *str="microsoft"; return str=="microsoft"
D. return "microsoft"=="miceosoft"
E. None of the above
问题分析:
1&7=1;
gcc下会对"ab" == "ab"警告:比较字面值是未定义的行为。但是结果也给出1.
还有一项是:char *s="abc";return s=="abc";
测试发现一般编译器都会优化,但是g++会警告。。。
解答:c语言中main函数若执行成功返回0,故A不对。7&1 = (00000111b & 00000001b ) = 1,B正确。C和D相同,先说D,常量字符串“microsoft”位于常量区,编译器一般都只保留一份,不会有重复,故D正确。C也是,char *str = "microsoft",也是将常量区中字符串的起始地址赋值给str,但我们不能通过str修改那个字符串,否则程序会崩溃,因为它在常量区。
VS2010汇编代码参考:
char *str = "microsoft"; mov dword ptr [str],offset string "microsoft" (12F7830h) int flag1 = (str == "microsoft"); xor eax,eax cmp dword ptr [str],offset string "microsoft" (12F7830h) sete al mov dword ptr [flag1],eax int flag2 = ("microsoft" == "microsoft"); mov eax,offset string "microsoft" (12F7830h) xor ecx,ecx cmp eax,offset string "microsoft" (12F7830h) sete cl mov dword ptr [flag2],ecx
11. If you computed 32 bit signed integers F and G from 32 bit signed X using F = X / 2 and G = (X>>1), and you found F!=G, this implies that(5 Points)
A. There is a compiler error
B. X is odd
C. X is negative
D. F - G = 1
E. G - F = 1
解答:B是不正确的,正整数不管是奇数还是偶数 (/ 2)与 (>>1)结果都相同。当X为负数的时候就会出问题,如-1不过管执行多少次(>> 1)永远是-1。X为负偶数时,没有问题,F等于G。X为负奇数是F-1等于G。F = abs(X)/2,G = (X-1)/2。
12. How many rectangles you can find from 3*4 grid?(5 Points)
A. 18
B. 20
C. 40
D. 60
E. None of above is correct
解答:3*4个格子,4*6条线。每个长方形都是由两条横线和两条竖线围成,求长方形的个数也就是求选出2条横线并和2条竖线共有多少种选法,在横线中选2条的选法有C(4,2),在竖线中选2条的选法有C(5,2),相乘得60。
13. One line can split a surface to 2 part, 2 line can split a surface to 4 part. Given 100 lines, no two parallel lines, no tree lines join at same point, how many parts can 100 line split?(5 Points)
A. 5051
B. 5053
C. 5510
D. 5511
解答:若当前有k条线,已经分成了f(k)个区域,则增加一条线会增加多少区域呢?分割一个区域要么是一条线段将一个区域分割成两个区域,要么是一条线段将一个区域分成两个区域,增加的区域就是增加的线段(或射线)的个数。由于没有三条线交于一点,因此新增加的线与之前k条线都有一个交点,因此就增加了k+1条线段(或射线),也就增加了k+1个区域。由此可得f(n) = f(n-1) + n。f(100) = f(99) + 100 = f(98) + 99 + 100 = f(1) + 2 + 3 + ... + 100 = 5051。
14. Which of the following sorting algorithm(s) is(are) stable sorting?(5 Points)
A. bubble sort
B. quick sort
C. heap sort
D. merge sort
E. Selection sort
解答:快速排序不稳定。如 5 6 3 16 2,以5作为partition的划分元素,一趟partition之后,绿色的6和2交换,然后5和1交换,变为1 2 3 5 66,所以不稳定。
堆排序不稳定。如最大堆3 2 1 1,堆排序的结果是1 1 2 3。
3
/
2 1
/
1
交换堆顶和尾部元素
1
/
2 1
/
3
调整堆为最大堆
2
/
1 1
/
3
交换堆顶和尾部元素
1
/
1 2
/
3
已是最大堆,交换堆顶和尾部元素
1
/
1 2
/
3
排序完成,黄色1到绿色1前面了。所以堆排序不稳定。
选择排序不稳定。如6 5 2 6 3 1,选择排序第一趟执行完后,绿色6和1交换,变为1 5 2 6 3 6,所以不稳定。
15. Model-View-Controller(MVC) is an architectural pattern that frequently used in web applications. Which of the following statement(s) is(are) correct:(5 Points)
A. Models often represent data and the business logics needed to manipulate the data in the application
B. A view is a (visual) representation of its model. It renders the model into a form suitable for interaction, typically a user interface element
C. A controller is the link between a user and the system. It accepts input from the user and instructs the model and a view to perform actions based on that input
D. The common practice of MVC in web applications is, the model receives GET or POST input from user and decides what to do with it, handing over to controller and which hand control to views(HTML-generating components)
E. None of the above
解答:MVC模型。
模型(Model):模型持有所有的数据、状态和程序逻辑。模型没有注意到视图和控制器,虽然它提供了操纵和检索状态的接口,并发送状态改变通知给观察者。
视图(View):用来呈现模型。视图通常直接从模型中取得它需要显示的数据。视图对象通常是空间,用来显示和编辑。
控制器(Controller):取得用户的输入并解读其对模型的意思。
16. we can recover the binary tree if given the output of(5 Points)
A. Preorder traversal and inorder traversal
B. Preorder traversal and postorder traversal
C. Inorder traversal and postorder traversal
D. Postorder traversal
解答:前序遍历和后续遍历不能恢复出原来的二叉树结构,因为存在不同的二叉树树,前序遍历和后续遍历都相同。如:
第一棵二叉树
1
/
2
前序遍历是1 2, 后序遍历是2 1。
另一棵二叉树
1
2
前序遍历是1 2, 后序遍历是2 1。
所以B不正确,D就更不正确了。
17. Given a string with n characters, suppose all the characters are different from each other, how many different substrings do we have?(5 Points)
A. n+1
B. n^2
C. n(n+1)/2
D. 2^n-1
E. n!
解答:长度为1的子串有n个,长度为2的子串有n-1个,长度为3的子串有n-2个,... ,长度为n的有1个,总共n(n+1)/2。
18. Given the following database table, how many rows will the following SQL statement update?(5 Points)
update Books set NumberOfCopies = NumberOfCopies+1 where AuthorID in Select AuthorID from Books group by AuthorID having sum(NumberOfCopies) <= 8
A. 1
B. 2
C. 3
D. 4
E. 5
解答:先看最内层,是选出以AuthorID分组的每组内NumberOfCopies之和小于等于8的AuthorID,结果只有2。然后外层,对所有AuthorID为2的元组的NumberOfCopies加1。共更新了两行。
19. What is the shortest path between node S and node T, given the graph below? Note: the numbers represent the lengths of the connected nodes.(13 Points)
A. 17
B. 18
C. 19
D. 20
E. 21
解答:最短路径问题。不多说了,看就能看出来,看不出来就按Dijkstra一步步来。
20. Given a set of N balls and one of which is defective (weighs less than others), you are allowed to weigh with a balance 3 times to find the defective. Which of the following are possible N?(13 Points)
A. 12
B. 16
C. 20
D. 24
E. 28
解答:12个,分成三组4,4,4,先拿出其中两组称量,若左边轻,则坏球在左边,若右边轻则坏球在右边,若平衡,则坏球在剩下的四个当中。这样一次称量就将球减少到4个。将4个分成两组2,2,若左边轻则坏球在左边,反之在右边。第二次称量将球减少到2个。剩下两个再称量一次显然就确定了。也有其他可行的分组方法。A正确。
16个,分成三组6,6,4,先称量两组6个球的,则坏球要么在4个当中,要么在两组6个当中的一组,4个的用两次可以确定坏球。6个的再分成2,2,2三组,同样可以用一次减少到两个球,最后确定坏球。也有其他可行的分组方法。B正确。
20个,分成6,6,8三组,若在6个当中,两次可以找出,若在8个当中,将其分成3,3,2三组,两次也可以确定。也有其他可行的分组方法。
24个,分成8,8,8。第一次称量减少到8个,剩下8个两次可以确定,也有其他可行的分组方法。
28个无法三次确定。
总之,3个球以内一次,可一次称量确定。4~9个球可两次称量确定。10~27个球可三次称量确定。对于三次称量,只要第一次分成的三组,每组不多于9个即可。