开发工程师面试题库Word文档下载推荐.docx
《开发工程师面试题库Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《开发工程师面试题库Word文档下载推荐.docx(91页珍藏版)》请在冰点文库上搜索。
![开发工程师面试题库Word文档下载推荐.docx](https://file1.bingdoc.com/fileroot1/2023-5/10/219991d2-8f7d-4e86-9eb4-8d5bc3e09a76/219991d2-8f7d-4e86-9eb4-8d5bc3e09a761.gif)
G.未初始化内存,无法确定
在C语言中,一维数组名表示数组的首地址,而且是一个指针.如上例num,
对&
num,表示指针的指针.意味着这里强制转换为二维数组指针.
这样&
num+1等同于num[5][1],为代码空间.(&
num+1)-1表示num[4][0].即num[4].所以这里答案是E.
扩展题目:
*((int*)(num+1)-1)
的值是多少?
Num是首指针,num+1是第二个元素指针,-1后又变成首指针.所以这里是答案是num[0]即,A.1
3.
以下哪些是程序间可靠的通讯方式(C),哪些可以用于跨主机通讯(C,D,F).Windows命名管道跨机器也可跨机器.
A.信号
B.管道
C.TCP
D.UDP
E.PIPE
F,.串口I/O
4.classa
public:
virtual
void
funa();
funb();
void
fun();
static
fund();
int
si;
private:
int
i;
char
c;
};
问:
在32位编译器默认情况下,sizeof(a)等于()字节?
A.28
B.25
C.24
D.20
E.16
F.12
G.8
答案在VC++下是12.这里需要考虑三个问题,一是虚函数表vtable的入口表地址,二是字节对齐.三,静态成员是所有对象共享,不计入sizeof空间.
在大部分C++的实现中,带有虚函数的类的前4个BYTE是虚函数vtable表的这个类入口地址.所以sizeof必须要加入这个4个byte的长度,除此外,类的sizoef()为所有数据成员总的sizeof之和,这里是inti,和charc.其中charc被字节对齐为4.这样总长度为
Sizeof(a)=sizeof(vtable)+size(int)+sizeof(char+pad)=12;
5.32位Windows系统或Linux系统下
struct
a;
b;
}A;
short
}B;
long
}C;
printf(“%d,%d,%d\n”,sizeof(A),sizeof(B),sizeof(C));
的执行结果为:
()
A.3,6,7
B.3,6,8
C.4,8,12
D.3,6,12
E.4,6,7
F.4,8,9
C语法的字节对齐规则有两种情况要字节对齐,在VC++,gcc测试都是如此
1)
对同一个数据类型(short,int,long)发生了跨段分布,(在32CPU里,即一个数据类型分布在两个段中)才会发生字节对齐.
2)
数据类型的首部和尾部必须有其一是与4对齐.而且违反上一规则.
l
Sizeof(A),sizeof(B)虽然总字节数不能被4整除.但刚好所有数据平均分布在以4为单位的各个段中.所以无需字节对齐,所以结果是3和6
struct{chara;
charb;
charc;
chard;
chare;
}F;
的sizoef(F)是等于5.
用以下实例更加清楚
struct{
chara[20];
shortb;
chara[21];
Sizeof(A)=22,sizoef(B)=24.因为前者没有发生跨段分布.后者,如果不字节对齐.a[21]占用最后一个段的首地址,b无法作到与首部与尾部与4对齐,只能在a[21]与b之间加入一个byte,使用b的尾部与4对齐.
C就是比较好理解.要补多个成12
6.
依据程序,以下选择中那个是对的?
(
)
classA
m_nA;
classB
m_nB;
classC:
publicA,publicB
m_nC;
voidf(void)
C*pC=newC;
B*pB=dynamic_cast<
B*>
(pC);
A*pA=dynamic_cast<
A*>
A.pC==pB,(int)pC==(int)B
B.pC==pB,(int)pC!
=(int)pB
C.pC!
=pB,(int)pC==(int)pB
D.pC!
=pB,(int)pC!
这里主要考多态..将程序变为如下比较易懂
stdio.h>
voidf1(void)
pC->
m_nA=1;
m_nB=2;
m_nC=3;
printf(“A=%x,B=%x,C=%x,iA=%d,iB=%d,iC=%d\n”,pA,pB,pC,(int)pA,(int)pB,(int)pC);
voidtest1();
intmain()
//test1();
f1();
getchar();
return0;
以上程序输出:
A=4318d0,B=4318d4,C=4318d0,iA=4397264,iB=4397268,iC=4397264
即C从,A,B继承下来,由下图可以知道pA=pC.而pB强制转换后,只能取到C中B的部分.所以pB在pC向后偏移4个BYTE,(即m_nA)的空间
7,请写出能匹配”[10]:
dddddd”和”[9]:
abcdegf”,不匹配”[a]:
xfdf”的正则表达式________,linux下支持正则的命令有:
___find,grep_________
8.如下程序:
inti=1,k=0;
long*pl=NULL;
char*pc=NULL;
if(k++&
&
i++)
k++,pl++,pc++;
if(i++||k++)
i++,pl++,pc++;
printf(“i=%d,k=%d,pl=%ld,pc=%ld\n”,i,k,(long)pl,(long)pc);
打印结果为__i=3,k=1,pl=4,pc=1________
主要测试逻辑表达式的短路操作.
操作中,前一个表达式为0,后一表达式不执行
||操作中,前一个表达式为1,后一表达式不执行
9.以下程序的输出为______________
#include<
usingstd:
:
cout;
voidf(void){
cout<
”A:
f”<
’‘;
virtualvoidg(void)
”A:
g”<
‘‘;
classB:
publicA
voidf(void)
“B:
f“<
voidg(void)
“B:
g“<
A*
pA=newB;
pA->
f();
g();
B*pB=(B*)pA;
pB->
A:
fB:
g
B:
f
B:
多态中虚函数调用.
f()为非虚函数,这样强制转换后,执行本类的同名函数.
G()为虚函数,指针总是执行虚函数,这就是多态..
10.下列代码的作用是删除listlTest中值为6的元素:
list<
int>
:
iteratorIndex=ITest.begin();
for(;
Index!
=ITest.end();
++Index)
if((*Index)==6)
ITest.erase(Index);
请问有什么错误____Index=ITest.erase(Index);
____________________,
STL的游标处理,erase已经将Index破坏掉,需要用新的Index,否则下一循环的++Index被破坏掉
请写出正确的代码,或者在原代码上修正.
11.找错误_以下程序:
char*ptr=malloc(100);
if(!
ptr)
…
//ptr指向的空间不够需要重新分配
ptr=realloc(ptr,200);
请问有什么错误___if(ptr==NULL)____________________,请写出正确的代码,或者在原代码上修正.
12.以下为windowNT下32位C++程序,请填写如下值
classmyclass
inta;
intb;
char*p=“hello”;
charstr[]=“world”;
myclassclasses[2];
void*p2=malloc(100);
sizeof(p)=_4__
sizeof(str)=_6_
sizeof(classes)=_16__
sizeof(p2)=_4___
13.直接在以下程序中的错误的行数后的填空栏中打叉
程序1:
intmain(void)
inti=10;
_____
int*constj=&
i;
_______
(*j)++;
____
j++;
___*_____
程序2:
inti=20;
constint*j=&
_________
*j++;
______
____*____
主要考const出现在*前后不同含意,const在*后表示指针本身不能改,const在*前面指针内容不能改,程序1中j不能修改指针,所以j++是错,程序2,j不能改改内容,所以
14.用C/C++代码实现以下要求:
从1-100中挑选出10个不同的数字,请把可能的所有组合打印出来.
15.有一个非常大的全局数组inta[],长度n超过2的24次方,写一个针对该数组的查找算法unsignedsearch(intvalue)(返回值下标),插入算法insert(intvalue,unsignedindex).再次注意该数组的长度很长.
题目不太清,可能可以把数值本身作下标.并且按顺序排序.
16.有两个单向链表,表头pHeader1,pHeader2,请写一个函数判断这两个链表是否有交叉.如果有交叉,给出交叉点.程序不能改变链表的内容,可以使用额外的空间,时间复杂度尽量小,最好给出两种解.(双重循环的解由于时间复杂度高,不算正解).
1.移动链表指针,如果最终
17.编写程序,将一棵树从根节点到叶子的所有最长路径都打印出来.比如一棵树从跟到最末端的叶子最远要经
过4个节点,那么就把到所有要经过4个节点才能到达的叶子的搜索路径(所有途径节点)都分别打印出来.
18.请分别对一个链表和一个数组进行排序,并指出你排序的算法名称以及为何选择该算法
数组可用交换法排序
19.有单向链表,其中节点结构为Node{intvalue;
Node*pNext};
只知道指向某个节点的指针pCurrent;
并且知道该节点不是尾节点,有什么办法把他删除吗?
要求不断链.
从链表头开始,找到pCurrent上一个结点pPrev,然后pPrev->
pNext=pCurrent->
pNext;
20.问题A:
用什么方法避免c/c++编程中的头文件重复包含?
问题B:
假设解决了重复包含问题,但是又需要在两个不同的头文件中引用各申明的类,应该如何处理?
具体代码如下:
在头文件Man.h中
….
ClassCman
CFacem_face;
在头文件Face.h中
ClassCFace
Cman*m_owner;
这样类CMan.CFace就相互引用了,该如何处理呢?
1.#ifndef….
#define…..
2.类的前向声明
21.多线程和单线程各自分别在什么时候效率更高?
多线程在并发,并且各线程无需访问共享数据情况详细最高
如果多线程过于频繁切换,或共享数据很多情况下,使用单线程较好
22.在程序设计中,对公共资源(比如缓冲区等)的操作和访问经常需要使用锁来进行保护,但在大并发系统中过多的锁会导致效率很低,通常有那些方法可以尽量避免或减少锁的使用?
减少锁的粒度,每次尽可能减少锁范围
采用队列处理,这样无需使用锁.
23.请详细阐述如何在release版本(windows程序或linux程序都可以)中,查找段错误问题.
可以用编译器生成map文件来定位源码.通过地址反查源码
24.假设你编译链接release版本后得到一个可执行程序(由多个cpp文件和H文件编译),结果可执行程序文件非常大,你如何找到造成文件太大的可能原因,可能的原因是什么?
使用一个已经初始化的巨大的全局数组
25.在编写C++赋值运算符时有哪些要注意的地方?
返回值,参数最好用引用
减少友元函数使用,移植有问题.
26.假设你是参与设计嫦娥卫星的嵌入式单板软件工程师,其中有一个快速搜索可能要用到哈希变或者平衡二叉树,要求不管什么条件下,单板必须在指定的短时间内有输出,你会采取那种算法?
为什么用这种算法,为什么不用另一种算法?
HASH.HASH访问速度较快.
27.strcpy()容易引起缓冲区溢出问题,请问有什么函数可以替代以减少风险,为什么?
strncpy
28.请指出spinlock,mutex,semaphore,criticalsection的作用与区别,都在哪些场合使用.
spin_lockLinux内核自旋锁.MutexWindows互质量,semaphorePOSIX,criticalsectionWindows
29.在哪些方法使阻塞模式的recv函数在没有收到数据的情况下返回(不能将socket修改为非阻塞模式)请描述得详细点.
使用select
30.有3个红色球,2个白色球,1个绿色球.取出两个不同颜色的球就能变成两个第三种颜色的球(比如:
取出1红球,1白球,就能变成2个绿球).问,最少几次变化能将所有球都变成同一颜色,说明步骤和原因?
31.单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。
比如一个链表是这样的:
1->
2->
3->
4->
5通过反转后成为5->
1。
最容易想到的方法遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。
源代码如下:
1.structlinka{
2.intdata;
3.linka*next;
4.};
5.voidreverse(linka*&
head){
6.if(head==NULL)
7.
return;
8.linka*pre,*cur,*ne;
9.pre=head;
10.cur=head->
next;
11.while(cur)
12.{
13.
ne=cur->
14.
cur->
next=pre;
15.
pre=cur;
16.
cur=ne;
17.}
18.head->
next=NULL;
19.head=pre;
20.}
还有一种利用递归的方法。
这种方法的基本思想是在反转当前节点之前先调用递归函数反转后续节点。
源代码如下。
不过这个方法有一个缺点,就是在反转后的最后一个结点会形成一个环,所以必须将函数的返回的节点的next域置为NULL。
因为要改变head指针,所以我用了引用。
算法的源代码如下:
1.linka*reverse(linka*p,linka*&
head)
2.{
3.if(p==NULL||p->
next==NULL)
4.{
5.
head=p;
6.
returnp;
7.}
8.else
9.{
10.
linka*tmp=reverse(p->
next,head);
11.
tmp->
next=p;
12.
13.}
14.}
32.已知String类定义如下:
classString
String(constchar*str=NULL);
//通用构造函数
String(constString&
another);
//拷贝构造函数
~String();
//析构函数String&
operater=(constString&
rhs);
//赋值函数
char*m_data;
//用于保存字符串
尝试写出类的成员函数实现。
答案:
String:
String(constchar*str)
if(str==NULL)//strlen在参数为NULL时会抛异常才会有这步判断
m_data=newchar[1];
m_data[0]=‘\0′;
else
m_data=newchar[strlen(str)+1];
strcpy(m_data,str);
another)
m_data=newchar[strlen(another.m_data)+1];
strcpy(m_data,other.m_data);
String&
String:
operator=(constString&
rhs)
if(this==&
return*this;
delete[]m_data;
//删除原来的数据,新开一块内存
m_data=newchar[strlen(rhs.m_data)+1];
strcpy(m_data,rhs.m_data);
~String()
delete[]m_data;
33.求下面函数的返回值(微软)
intfunc(x)
intcountx=0;
while(x)
countx++;
x=x&
(x-1);
returncountx;
假定x=9999。
8
思路:
将x转化为2进制,看含有的1的个数。
34.
什么是“引用”?
申明和使用“引用”要注意哪些问题?
答:
引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。
申明一个引用的时候,切记要对其进行初始化。
引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。
声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。
不能建立数组的引用。
45.
将“引用”作为函数参数有哪些特点?
(1)传递引用给函数与传递指针的效果是一样的。
这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。
(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;
而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本