您好,欢迎来到智榕旅游。
搜索
您的当前位置:首页C与C++面试题汇总1

C与C++面试题汇总1

来源:智榕旅游
C语言

1.static有什么用途?(请至少说明两种)1)变量的作用域2)设置变量的存储域2.引用与指针有什么区别?

1)引用必须被初始化,指针不必。

2)引用初始化以后不能被改变,指针可以改变所指的对象。3)不存在指向空值的引用,但是存在指向空值的指针。3.描述实时系统的基本特性

在特定时间内完成特定的任务,实时性与可靠性

4.全局变量和局部变量在内存中是否有区别?如果有,是什么区别?全局变量储存在静态数据库,局部变量在堆栈5.什么是平衡二叉树?

左右子树都是平衡二叉树且左右子树的深度差值的绝对值不大于16.堆栈溢出一般是由什么原因导致的?

没有回收垃圾资源

7.什么函数不能声明为虚函数?

constructor

8.冒泡排序算法的时间复杂度是什么?

O(n^2)

9.写出floatx与“零值”比较的if语句。

if(x>0.000001&&x<-0.000001)

10.Internet采用哪种网络协议?该协议的主要层次结构?

tcp/ip应用层/传输层/网络层/数据链路层/物理层11.Internet物理地址和IP地址转换采用什么协议?

ARP(AddressResolutionProtocol)(地址解析協議)12.IP地址的编码分为哪俩部分?

IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。

13.用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。循环链表,用取余操作做

14.不能做switch()的参数类型是:

switch的参数不能为实型。15.局部变量能否和全局变量重名?

答:能,局部会屏蔽全局。要用全局变量,需要使用\"::\"

局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内16.如何引用一个已经定义过的全局变量?答:extern

可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在

编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错

17.全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?答:可以,在不同的C文件中以static形式来声明同名全局变量。可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错

18.语句for(;1;)有什么问题?它是什么意思?答:和while(1)相同。

19.do……while和while……do有什么区别?

答:前一个循环一遍再判断,后一个判断以后再循环20.请写出下列代码的输出内容#includemain(){

inta,b,c,d;a=10;b=a++;c=++a;

d=10*a++;

printf(\"b,c,d:%d,%d,%d\",b,c,d);return0;}

答:10,12,120

21.static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?

全局变量(外部变量)的说明之前再冠以static就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。

从以上分析可以看出,把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,了它的使用范围。

static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;

static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

22.程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。23.设有以下说明和定义:

typedefunion{longi;intk[5];charc;}DATE;structdata{intcat;DATEcow;doubledog;}too;DATEmax;

则语句printf(\"%d\date)+sizeof(max));的执行结果是:___52____答:DATE是一个union,变量公用空间.里面最大的变量类型是int[5],占用20个字节.所以它的大小是20

data是一个struct,每个变量分开占用空间.依次为int4+DATE20+double8=32.

所以结果是20+32=52.

当然...在某些16位编辑器下,int可能是2字节,那么结果是int2+DATE10+double8=2024.队列和栈有什么区别?队列先进先出,栈后进先出25.写出下列代码的输出内容#includeintinc(inta){

return(++a);}

intmulti(int*a,int*b,int*c){

return(*c=*a**b);}

typedefint(FUNC1)(intin);

typedefint(FUNC2)(int*,int*,int*);voidshow(FUNC2fun,intarg1,int*arg2){

INCp=&inc;

inttemp=p(arg1);

fun(&temp,&arg1,arg2);printf(\"%d\\n\}

main(){

inta;

show(multi,10,&a);

return0;}

答:110

26.请找出下面代码中的所以错误

说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”1、#include\"string.h\"2、main()3、{

4、char*src=\"hello,world\";5、char*dest=NULL;6、intlen=strlen(src);

7、dest=(char*)malloc(len);8、char*d=dest;9、char*s=src[len];10、while(len--!=0)11、d++=s--;

12、printf(\"%s\13、return0;14、}答:方法1:intmain(){

char*src=\"hello,world\";intlen=strlen(src);

char*dest=(char*)malloc(len+1);//要为\\0分配一个空间char*d=dest;

char*s=&src[len-1];//指向最后一个字符while(len--!=0)*d++=*s--;

*d=0;//尾部要加\\0printf(\"%s\\n\

free(dest);//使用完,应当释放空间,以免造成内存汇泄露return0;}

方法2:

#include#includemain(){

charstr[]=\"hello,world\";intlen=strlen(str);

27.队列的功能?要求给出算法和思路!设2个栈为A,B,一开始均为空.

入队:

将新元素push入栈A;

出队:

(1)判断栈B是否为空;

(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;(3)将栈B的栈顶元素pop出;

这样实现的队列入队和出队的平摊复杂度都还是O(1),比上面的几种方法要好。

28.在c语言库函数中将一个字符转换成整型的函数是atool()吗,这个函数的原型是什么?函数名:atol

功能:把字符串转换成长整型数

用法:longatol(constchar*nptr);程序例:

#include#includeintmain(void){

longl;

char*str=\"987632\";l=atol(lstr);

printf(\"string=%sinteger=%ld\\n\str,l);return(0);}

29.对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?

用宏定义,c++用inline

30.直接链接两个信令点的一组链路称作什么?PPP点到点连接

31.接入网用的是什么接口?32.voip都用了那些协议?33.软件测试都有那些种类?

黑盒:针对系统功能的测试白合:测试函数功能,各函数接口34.确定模块的功能和模块的接口是在软件设计的那个队段完成的?概要设计阶段35.enumstring{x1,x2,

x3=10,

x4,x5,}x;

问x=0x801005,0x8010f4;36.unsignedchar*p1;unsignedlong*p2;

p1=(unsignedchar*)0x801000;p2=(unsignedlong*)0x810000;请问p1+5=;p2+5=;37.三.选择题:

1.Ethternet链接到Internet用到以下那个协议?A.HDLC;B.ARP;C.UDP;D.TCP;E.ID2.属于网络层协议的是:

A.TCP;B.IP;C.ICMP;D.X.253.Windows消息调度机制是:

A.指令队列;B.指令堆栈;C.消息队列;D.消息堆栈;4.unsignedshorthash(unsignedshortkey){

return(key>>)%256}

请问hash(16),hash(256)的值分别是:A.1.16;B.8.32;C.4.16;D.1.32四.找错题:

1.请问下面程序有什么错误?inta[60][250][1000],i,j,k;for(k=0;k<=1000;k++)for(j=0;j<250;j++)for(i=0;i<60;i++)a[i][j][k]=0;

把循环语句内外换一下2.#defineMax_CB500

voidLmiQueryCSmd(StructMSgCB*pmsg){

unsignedcharucCmdNum;......

for(ucCmdNum=0;ucCmdNum死循环

3.以下是求一个数的平方的程序,请找出错误:#defineSQUARE(a)((a)*(a))

inta=5;intb;

b=SQUARE(a++);

4.typedefunsignedcharBYTE

intexamply_fun(BYTEgt_len;BYTE*gt_code){

BYTE*gt_buf;

gt_buf=(BYTE*)MALLOC(Max_GT_Length);......

if(gt_len>Max_GT_Length){

returnGT_Length_ERROR;}.......}

五.问答题:

1.IPPhone的原理是什么?IPV6

2.TCP/IP通信建立的过程怎样,端口有什么作用?三次握手,确定是哪个应用程序使用该协议

3.1号信令和7号信令有什么区别,我国某前广泛使用的是那一种?4.列举5种以上的电话新业务?

微软亚洲技术中心的面试题!!!1.进程和线程的差别。

线程是指进程内的一个执行单元,也是进程内的可调度实体.与进程的区别:

(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行

(3)拥有资源:进程是拥有资源的一个单位,线程不拥有系统资源,但可以访问隶属于进程的资源.

(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。2.测试方法

人工测试:个人复查、抽查和会审机器测试:黑盒测试和白盒测试

2.Heap与stack的差别。Heap是堆,stack是栈。

Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。Stack空间有限,Heap是很大的自由存储区

C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数

调用时参数的传递也在栈上进行

3.Windows下的内存是如何管理的?4.介绍.Net和.Net的安全性。

5.客户端如何访问.Net组件实现WebService?6.C/C++编译器中虚表是如何完成的?

7.谈谈COM的线程模型。然后讨论进程内/外组件的差别。8.谈谈IA32下的分页机制

小页(4K)两级分页模式,大页(4M)一级

9.给两个变量,如何找出一个带环单链表中是什么地方出现环的?一个递增一,一个递增二,他们指向同一个接点时就是环出现的地方10.在IA32中一共有多少种办法从用户态跳到内核态?

通过调用门,从ring3到ring0,中断从ring3到ring0,进入vm86等等11.如果只想让程序有一个实例运行,不能运行两个。像winamp一样,只能开一个窗口,怎样实现?

用内存映射或全局原子(互斥变量)、查找窗口句柄..

FindWindow,互斥,写标志到文件或注册表,共享内存。.12.如何截取键盘的响应,让所有的‘a’变成‘b’?键盘钩子SetWindowsHookEx

13.Apartment在COM中有什么用?为什么要引入?14.存储过程是什么?有什么用?有什么优点?

我的理解就是一堆sql的集合,可以建立非常复杂的查询,编译运行,所以运行一次后,以后再运行速度比单独执行SQL快很多15.Template有什么特点?什么时候用?16.谈谈WindowsDNA结构的特点和优点。

网络编程中设计并发服务器,使用多进程与多线程,请问有什么区别?1,进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。

2,线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有的执行序列。两者都可以提高程序的并发度,提高程序运行效率和响应时间。

线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

思科

1.用宏定义写出swap(x,y)#defineswap(x,y)\\x=x+y;\\y=x-y;\\x=x-y;

2.数组a[N],存放了1至N-1个数,其中某个数重复一次。写一个函数,找出被重复的数字.时间复杂度必须为o(N)函数原型:

intdo_dup(inta[],intN)

3一语句实现x是否为2的若干次幂的判断inti=512;

cout<4.unsignedintintvert(unsignedintx,intp,intn)实现对x的进行转换,p为起始转化位,n为需要转换的长度,假设起始点在右边.如x=0b00010001,p=4,n=3转换后x=0b01100001

unsignedintintvert(unsignedintx,intp,intn){unsignedint_t=0;unsignedint_a=1;

for(inti=0;i_a=_a<<1;}

_t=_t<慧通:

什么是预编译何时需要预编译:

1、总是使用不经常改动的大型代码体。

2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。char*constp;charconst*pconstchar*p

上述三个有什么区别?

char*constp;//常量指针,p的值不可以修改

charconst*p;//指向常量的指针,指向的常量值不可以改constchar*p;//和charconst*pcharstr1[]=\"abc\";charstr2[]=\"abc\";constcharstr3[]=\"abc\";constcharstr4[]=\"abc\";constchar*str5=\"abc\";constchar*str6=\"abc\";char*str7=\"abc\";

char*str8=\"abc\";

coutcoutcoutcout<<<<<<<<((((str1str3str5str7========str2str4str6str8))))<<<<<<<结果是:0011

解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域。

12.以下代码中的两个sizeof用法有问题吗?[C易]

voidUpperCase(charstr[])//将str中的小写字母转换成大写字母{

for(size_ti=0;icharstr[]=\"aBcDe\";

cout<<\"str字符长度为:\"<答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。

一个32位的机器,该机器的指针是多少位

指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。main(){

inta[5]={1,2,3,4,5};int*ptr=(int*)(&a+1);

printf(\"%d,%d\}

输出:2,5

*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5

&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)int*ptr=(int*)(&a+1);

则ptr实际是&(a[5]),也就是a+5原因如下:

&a是数组指针,其类型为int(*)[5];而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同

a是长度为5的int数组指针,所以要加5*sizeof(int)所以ptr实际是a[5]

但是prt与(&a+1)类型是不一样的(这点很重要)所以prt-1只会减去sizeof(int*)

a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].

1.请问以下代码有什么问题:intmain(){

chara;

char*str=&a;

strcpy(str,\"hello\");printf(str);return0;}

没有为str分配内存空间,将会发生异常

问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。

char*s=\"AAA\";printf(\"%s\s[0]='B';

printf(\"%s\有什么错?

\"AAA\"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。

cosntchar*s=\"AAA\";

然后又因为是常量,所以对是s[0]的赋值操作是不合法的。1、写一个“标准”宏,这个宏输入两个参数并返回较小的一个。.#defineMin(X,Y)((X)>(Y)?(Y):(X))//结尾没有;

2、嵌入式系统中经常要用到无限循环,你怎么用C编写死循环。while(1){}或者for(;;)

3、关键字static的作用是什么?

定义静态变量

4、关键字const有什么含意?表示常量不可以修改的变量。

5、关键字volatile有什么含意?并举出三个不同的例子?提示编译器对象的值可能在编译器未监测到的情况下改变。

int(*s[10])(int)表示的是什么啊

int(*s[10])(int)函数指针数组,每个指针指向一个intfunc(intparam)的函数。

1.有以下表达式:

inta=248;b=4;intconstc=21;constint*d=&a;int*conste=&b;intconst*fconst=&a;请问下列表达式哪些会被编译器禁止?为什么?*c=32;d=&b;*d=43;e=34;e=&a;f=0x321f;*c这是个什么东东,禁止*d说了是const,禁止e=&a说了是const禁止const*fconst=&a;禁止2.交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3;有两种解法,一种用算术算法,一种用^(异或)a=a+b;b=a-b;a=a-b;or

a=a^b;//只能对int,char..b=a^b;a=a^b;or

a^=b^=a;

3.c和c++中的struct有什么不同?

c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private4.#include#include

voidgetmemory(char*p){

p=(char*)malloc(100);strcpy(p,\"helloworld\");}

intmain()

{

char*str=NULL;getmemory(str);printf(\"%s/n\free(str);return0;}

程序崩溃,getmemory中的malloc不能返回动态内存,free()对str操作很危险

5.charszstr[10];

strcpy(szstr,\"01234567\");产生什么结果?为什么?

长度不一样,会造成非法的OS

6.列举几种进程的同步机制,并比较其优缺点。原子操作信号量机制自旋锁

管程,会合,分布式系统

7.进程之间通信的途径共享存储系统消息传递系统

管道:以文件系统为基础11.进程死锁的原因

资源竞争及进程推进顺序非法12.死锁的4个必要条件

互斥、请求保持、不可剥夺、环路13.死锁的处理

鸵鸟策略、预防策略、避免策略、检测与解除死锁15.操作系统中进程调度策略有哪几种?

FCFS(先来先服务),优先级,时间片轮转,多级反馈8.类的静态成员和非静态成员有何区别?

类的静态成员每个类只有一个,非静态成员每个对象一个9.纯虚函数如何定义?使用时应注意什么?virtualvoidf()=0;是接口,子类必须要实现10.数组和链表的区别

数组:数据顺序存储,固定大小

连表:数据可以随机存储,大小可动态改变

12.ISO的七层模型是什么?tcp/udp是属于哪一层?tcp/udp有何优缺点?应用层表示层

会话层运输层网络层物理链路层物理层

tcp/udp属于运输层

TCP服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。

与TCP不同,UDP并不提供对IP协议的可靠机制、流控制以及错误恢复功能等。由于UDP比较简单,UDP头包含很少的字节,比TCP负载消耗少。

tcp:提供稳定的传输服务,有流量控制,缺点是包头大,冗余性不好udp:不提供稳定的服务,包头小,开销小

1:(void*)ptr和(*(void**))ptr的结果是否相同?其中ptr为同一个指针

.(void*)ptr和(*(void**))ptr值是相同的2:intmain(){

intx=3;

printf(\"%d\return1;

}

问函数既然不会被其它函数调用,为什么要返回1?

mian中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息

1,要对绝对地址0x100000赋值,我们可以用(unsignedint*)0x100000=1234;

那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?*((void(*)())0x100000)();

首先要将0x100000强制转换成函数指针,即:(void(*)())0x100000然后再调用它:

*((void(*)())0x100000)();用typedef可以看得更直观些:typedefvoid(*)()voidFuncPtr;*((voidFuncPtr)0x100000)();

2,已知一个数组table,用一个宏定义,求出数据的元素个数#defineNTBL

#defineNTBL(sizeof(table)/sizeof(table[0]))

面试题:线程与进程的区别和联系?线程是否具有相同的堆栈?dll是否有的堆栈?

进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程。

每个线程有自己的堆栈。

DLL中有没有的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为DLL中的代码是被某些线程所执行,只有线程拥有堆栈,如果DLL中的代码是EXE中的线程所调用,那么这个时候是不是说这个DLL没有自己的堆栈?如果DLL中的代码是由DLL自己创建的线程所执行,那么是不是说DLL有的堆栈?

以上讲的是堆栈,如果对于堆来说,每个DLL有自己的堆,所以如果是从DLL中动态分配的内存,最好是从DLL中删除,如果你从DLL中分配内存,然后在EXE中,或者另外一个DLL中删除,很有可能导致程序崩溃

unsignedshortA=10;printf(\"~A=%u\\n\~A);charc=128;

printf(\"c=%d\\n\

输出多少?并分析过程

第一题,~A=0xfffffff5,int值为-11,但输出的是uint。所以输出4294967285第二题,c=0x10,输出的是int,最高位为1,是负数,所以它的值就是0x00的补码就是128,所以输出-128。

这两道题都是在考察二进制向int或uint转换时的最高位处理。分析下面的程序:

voidGetMemory(char**p,intnum){

*p=(char*)malloc(num);}

intmain(){

char*str=NULL;GetMemory(&str,100);strcpy(str,\"hello\");

free(str);

if(str!=NULL){

strcpy(str,\"world\");}

printf(\"\\nstris%s\getchar();}

问输出结果是什么?希望大家能说说原因,先谢谢了输出strisworld。

free只是释放的str指向的内存空间,它本身的值还是存在的.所以free之后,有一个好的习惯就是将str=NULL.

此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,

尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。

这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。

当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的,只不过。。。。。。。。楼上都说过了,最好别这么干。chara[10],strlen(a)为什么等于15?运行的结果#include\"stdio.h\"#include\"string.h\"voidmain(){

charaa[10];

printf(\"%d\}

sizeof()和初不初始化,没有关系;strlen()和初始化有关。

char(*str)[20];/*str是一个数组指针,即指向数组的指针.*/

char*str[20];/*str是一个指针数组,其元素为指针型数据.*/

longa=0x801010;a+5=?

0x801010用二进制表示为:“100000000001000000010000”,十进制的值为8392720,再加上5就是8392725罗1)给定结构structA{

chart:4;chark:4;

unsignedshorti:8;unsignedlongm;};问sizeof(A)=?给定结构structA{

chart:4;4位chark:4;4位

unsignedshorti:8;8位

unsignedlongm;//偏移2字节保证4字节对齐};//共8字节

2)下面的函数实现在一个数上加一个数,有什么错误?请改正。intadd_n(intn){

staticinti=100;i+=n;returni;}

当你第二次调用时得不到正确的结果,难道你写个函数就是为了调用一次?问题就出在static上?

//帮忙分析一下

#include#include#include#include#include#includetypedefstructAA{

intb1:5;intb2:2;}AA;

voidmain()

{

AAaa;

charcc[100];

strcpy(cc,\"01234567abcdefghijklmnopqrstuvwxyz\");memcpy(&aa,cc,sizeof(AA));cout<答案是-16和1

首先sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.经过strcpy和memcpy后,aa的4个字节所存放的值是:

0,1,2,3的ASC码,即00110000,00110001,00110010,00110011所以,最后一步:显示的是这4个字节的前5位,和之后的2位分别为:10000,和01因为int是有正负之分所以:答案是-16和1求函数返回值,输入x=9999;intfunc(x){

intcountx=0;while(x){

countx++;x=x&(x-1);}

returncountx;}

结果呢?

知道了这是统计9999的二进制数值中有多少个1的函数,且有9999=9×1024+512+256+15

9×1024中含有1的个数为2;512中含有1的个数为1;256中含有1的个数为1;15中含有1的个数为4;

故共有1的个数为8,结果为8。

1000-1=0111,正好是原数取反。这就是原理。用这种方法来求1的个数是很效率很高的。不必去一个一个地移位。循环次数最少。

inta,b,c请写函数实现C=a+b,不可以改变数据类型,如将c改为longint,关键是如何处理溢出问题

booladd(inta,intb,int*c){

*c=a+b;

return(a>0&&b>0&&(*ca||*c>b)));}

分析:structbit{inta:3;intb:2;intc:3;};

intmain(){bits;

char*c=(char*)&s;

cout<cout<printf(\"%x\return0;}

输出为什么是41-1-4ffffffff

因为0x99在内存中表示为10011001,a=001,b=11,c=100当c为有符合数时,c=100,最高1为表示c为负数,负数在计算机用补码表示,所以c=-4;同理b=-1;

当c为有符合数时,c=100,即c=4,同理b=3

位域:

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1两种状态,用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:

struct位域结构名{位域列表};

其中位域列表的形式为:类型说明符位域名:位域长度例如:structbs{

inta:8;intb:2;intc:6;};

位域变量的说明与结构变量说明的方式相同。可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:structbs{

inta:8;intb:2;intc:6;}data;

说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明:

1.一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:structbs{

unsigneda:4

unsigned:0/*空域*/

unsignedb:4/*从下一单元开始存放*/unsignedc:4}

在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。

2.由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。

3.位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:structk{

inta:1

int:2/*该2位不能使用*/intb:3

intc:2};

从以上分析可以看出,位域在本质上就是一种结构类型,不过其成员是按二进位分配的。

二、位域的使用位域的使用和结构成员的使用相同,其一般形式为:位域变量名•位域名位域允许用各种格式输出。main(){structbs{

unsigneda:1;unsignedb:3;unsignedc:4;}bit,*pbit;bit.a=1;bit.b=7;bit.c=15;pri

改错:

#includeintmain(void){int**p;

intarr[100];p=&arr;

return0;}

解答:

搞错了,是指针类型不同,int**p;//二级指针

&arr;//得到的是指向第一维为100的数组的指针#includeintmain(void){int**p,*q;intarr[100];q=arr;p=&q;return0;}

下面这个程序执行后会有什么错误或者效果:#defineMAX255intmain(){

unsignedcharA[MAX],i;//i被定义为unsignedcharfor(i=0;i<=MAX;i++)A[i]=i;}

解答:死循环加数组越界访问(C/C++不进行数组越界检查)MAX=255

数组A的下标范围为:0..MAX-1,这是其一..其二.当i循环到255时,循环内执行:A[255]=255;

这句本身没有问题..但是返回for(i=0;i<=MAX;i++)语句时,

由于unsignedchar的取值范围在(0..255),i++以后i又为0了..无限循环下去.structname1{charstr;shortx;intnum;}

structname2{charstr;intnum;shortx;}

sizeof(structname1)=8,sizeof(structname2)=12

在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就是12字节。

intel:

A.c和B.c两个c文件中使用了两个相同名字的static变量,编译的时候会不会有问题?这两个static变量会保存到哪里(栈还是堆或者其他的)?

static的全局变量,表明这个变量仅在本模块中有意义,不会影响其他模块。他们都放在数据区,但是编译器对他们的命名是不同的。

如果要使变量在其他模块也有意义的话,需要使用extern关键字。structs1{

inti:8;intj:4;inta:3;doubleb;};structs2{

inti:8;intj:4;doubleb;inta:3;};

printf(\"sizeof(s1)=%d\\n\sizeof(s1));printf(\"sizeof(s2)=%d\\n\sizeof(s2));result:16,24第一个structs1{

inti:8;intj:4;inta:3;doubleb;};

理论上是这样的,首先是i在相对0的位置,占8位一个字节,然后,j就在相对一个字节的位置,由于一个位置的字节数是4位的倍数,因此不用对齐,就放在那里了,然后是a,要在3位的倍数关系的位置上,因此要移一位,在15位的位置上放下,目前总共是18位,折算过来是2字节2位的样子,由于double是8字节的,因此要在相对0要是8个字节的位置上放下,因此从18位开始到8个字节之间的位置被忽略,直接放在8字节的位置了,因此,总共是16字节。

第二个最后会对照是不是结构体内最大数据的倍数,不是的话,会补成是最大数据的倍数

1)读文件file1.txt的内容(例如):123456

输出到file2.txt:563412

(逆序)

2)输出和为一个给定整数的所有组合

例如n=5

5=1+4;5=2+3(相加的数不能重复)则输出

1,4;2,3。望高手赐教!!第一题,注意可增长数组的应用.#include#includeint{intintint

main(void)

MAX=10;

*a=(int*)malloc(MAX*sizeof(int));*b;

FILE*fp1;FILE*fp2;

fp1=fopen(\"a.txt\if(fp1==NULL){printf(\"error1\");exit(-1);}

fp2=fopen(\"b.txt\if(fp2==NULL){printf(\"error2\");exit(-1);}inti=0;intj=0;

while(fscanf(fp1,\"%d\!=EOF){i++;j++;

if(i>=MAX){

MAX=2*MAX;

b=(int*)realloc(a,MAX*sizeof(int));if(b==NULL){

printf(\"error3\");exit(-1);}

a=b;}}

for(;--j>=0;)

fprintf(fp2,\"%d\\n\fclose(fp1);fclose(fp2);return0;

}

第二题.

#includeintmain(void){

unsignedlonginti,j,k;

printf(\"pleaseinputthenumber\\n\");scanf(\"%d\if(i%2==0)j=i/2;else

j=i/2+1;

printf(\"Theresultis\\n\");for(k=0;kprintf(\"%d=%d+%d\\n\-k);return0;}

#includevoidmain(){

unsignedlonginta,i=1;scanf(\"%d\if(a%2==0)

{

for(i=1;ifor(i=1;i<=a/2;i++)printf(\"%d,%d\}

兄弟,这样的题目若是做不出来实在是有些不应该,给你一个递规反向输出字符串的例子,可谓是反序的经典例程.voidinverse(char*p){

if(*p=='\\0')return;

inverse(p+1);printf(\"%c\*p);}

intmain(intargc,char*argv[]){

inverse(\"abc\\0\");return0;}

借签了楼上的“递规反向输出”#include

voidtest(FILE*fread,FILE*fwrite){

charbuf[1024]={0};

if(!fgets(buf,sizeof(buf),fread))return;

test(fread,fwrite);fputs(buf,fwrite);}

intmain(intargc,char*argv[]){

FILE*fr=NULL;FILE*fw=NULL;

fr=fopen(\"data\\"rb\");

fw=fopen(\"dataout\\"wb\");test(fr,fw);

fclose(fr);fclose(fw);return0;}

在对齐为4的情况下structBBB{

longnum;char*name;shortintdata;charha;shortba[5];}*p;

p=0x1000000;p+0x200=____;

(Ulong)p+0x200=____;(char*)p+0x200=____;

希望各位达人给出答案和原因,谢谢拉解答:假设在32位CPU上,sizeof(long)=4bytessizeof(char*)=4bytes

sizeof(shortint)=sizeof(short)=2bytessizeof(char)=1bytes

由于是4字节对齐,

sizeof(structBBB)=sizeof(*p)

=4+4+2+1+1/*补齐*/+2*5+2/*补齐*/=24bytes(经Dev-C++验证)

p=0x1000000;p+0x200=____;

=0x1000000+0x200*24(Ulong)p+0x200=____;=0x1000000+0x200(char*)p+0x200=____;=0x1000000+0x200*4你可以参考一下指针运算的细节

写一段程序,找出数组中第k大小的数,输出数所在的位置。例如{2,4,

3,4,7}中,第一大的数是7,位置在4。第二大、第三大的数都是4,位置在1、3随便输出哪一个均可。函数接口为:intfind_orderk(constint*narry,constintn,constintk)要求算法复杂度不能是O(n^2)谢谢!

可以先用快速排序进行排序,其中用另外一个进行地址查找代码如下,在VC++6.0运行通过。给分吧^-^//快速排序

#includeusingnamespacestd;

intPartition(int*L,intlow,inthigh){

inttemp=L[low];intpt=L[low];

while(lowwhile(low=pt)--high;

L[low]=L[high];

while(lowL[low]=temp;}

L[low]=temp;returnlow;}

voidQSort(int*L,intlow,inthigh){

if(lowintpl=Partition(L,low,high);QSort(L,low,pl-1);QSort(L,pl+1,high);}}

intmain(){

intnarry[100],addr[100];intsum=1,t;

cout<<\"Inputnumber:\"<>t;

while(t!=-1){

narry[sum]=t;addr[sum-1]=t;sum++;cin>>t;}

sum-=1;

QSort(narry,1,sum);for(inti=1;i<=sum;i++)cout<intk;

cout<<\"Pleaseinputplaceyouwant:\"<>k;

intaa=1;intkk=0;for(;;){

if(aa==k)break;

if(narry[kk]!=narry[kk+1]){

aa+=1;kk++;}}

cout<<\"TheNO.\"<cout<<\"Andit'splaceis:\";for(i=0;iif(addr[i]==narry[sum-kk])cout<return0;}

1、找错

Voidtest1(){

charstring[10];

char*str1=\"01234567\";

strcpy(string,str1);//溢出,应该包括一个存放'\\0'的字符string[11]}

Voidtest2(){

charstring[10],str1[10];for(I=0;I<10;I++){

str1[i]='a';}

strcpy(string,str1);//I,i没有声明。}

Voidtest3(char*str1){

charstring[10];

if(strlen(str1)<=10)//改成<10,字符溢出,将strlen改为sizeof也可以{

strcpy(string,str1);}}

2.

voidg(int**);intmain(){

intline[10],i;

int*p=line;//p是地址的地址for(i=0;i<10;i++){

*p=i;

g(&p);//数组对应的值加1}

for(i=0;i<10;i++)printf(\"%d\\n\return0;}

voidg(int**p){

(**p)++;

(*p)++;//无效}

输出:123456710

3.写出程序运行结果intsum(inta){

autointc=0;staticintb=3;c+=1;b+=2;

return(a+b+c);}

voidmain(){intI;inta=2;

for(I=0;I<5;I++)

{

printf(\"%d,\sum(a));}}

//static会保存上次结果,记住这一点,剩下的自己写输出:8,10,12,14,16,

4.

intfunc(inta){

intb;switch(a){

case1:30;case2:20;case3:16;default:0}

returnb;}

则func(1)=?

//b定义后就没有赋值。

5:

inta[3];

a[0]=0;a[1]=1;a[2]=2;int*p,*q;p=a;

q=&a[2];

则a[q-p]=a[2]

解释:指针一次移动一个int但计数为1

今天早上的面试题9道,比较难,向牛人请教,国内的一牛公司,坐落在北京北四环某大厦:

1、线形表a、b为两个有序升序的线形表,编写一程序,使两个有序线形表合并成一个有序升序线形表h;

答案在请化大学严锐敏《数据结构第二版》第二章例题,数据结构当中,这个叫做:两路归并排序

Linklist*unio(Linklist*p,Linklist*q){linklist*R,*pa,*qa,*ra;pa=p;qa=q;

R=ra=p;

while(pa->next!=NULL&&qa->next!=NULL){if(pa->data>qa->data){ra->next=qa;qa=qa->next;}else{

ra->next=pa;pa=pa->next;}}

if(pa->next!=NULL)ra->next=pa;

if(qa->next!=NULL)ra->next==qa;returnR;}

2、运用四色定理,为N个局域举行配色,颜色为1、2、3、4四种,另有数组adj[][N],如adj[i][j]=1则表示i区域与j区域相邻,数组color[N],如color[i]=1,表示i区域的颜色为1号颜色。四色填充

3、用递归算法判断数组a[N]是否为一个递增数组。

递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回false结束:

boolfun(inta[],intn){

if(n==1)returntrue;if(n==2)

returna[n-1]>=a[n-2];

returnfun(a,n-1)&&(a[n-1]>=a[n-2]);}

4、编写算法,从10亿个浮点数当中,选出其中最大的10000个。用外部排序,在《数据结构》书上有

《计算方法导论》在找到第n大的数的算法上加工5、编写一unix程序,防止僵尸进程的出现.

Top

回复人:free131(白日?做梦!)()信誉:1002006-4-1710:17:34得

分:0

?

同学的4道面试题,应聘的职位是搜索引擎工程师,后两道超级难,(希望大家多给一些算发)

1.给两个数组和他们的大小,还有一动态开辟的内存,求交集,把交集放到动态内存dongtai,并且返回交集个数

longjiaoji(long*a[],longb[],long*alength,longblength,long*dongtai[])

2.单连表的建立,把'a'--'z'26个字母插入到连表中,并且倒叙,还要打印!方法1:

typedefstructval{intdate_1;structval*next;}*p;

voidmain(void){charc;

for(c=122;c>=97;c--){p.date=c;p=p->next;}

p.next=NULL;}}

方法2:

node*p=NULL;node*q=NULL;

node*head=(node*)malloc(sizeof(node));head->data='';head->next=NULL;

node*first=(node*)malloc(sizeof(node));

first->data='a';first->next=NULL;head->next=first;p=first;

intlongth='z'-'b';inti=0;

while(i<=longth)

{

node*temp=(node*)malloc(sizeof(node));

temp->data='b'+i;temp->next=NULL;q=temp;head->next=temp;temp->next=p;p=q;i++;}

print(head);

3.可怕的题目终于来了

象搜索的输入信息是一个字符串,统计300万输入信息中的最热门的前十条,我们每次输入的一个字符串为不超过255byte,内存使用只有1G,请描述思想,写出算发(c语言),空间和时间复杂度,

4.国内的一些帖吧,如baidu,有几十万个主题,假设每一个主题都有上亿的跟帖子,怎么样设计这个系统速度最好,请描述思想,写出算发(c语言),空间和时间复杂度,

#includestring.hmain(void)

{char*src=\"hello,world\";char*dest=NULL;

dest=(char*)malloc(strlen(src));intlen=strlen(str);char*d=dest;char*s=src[len];while(len--!=0)d++=s--;

printf(\"%s\}

找出错误!!

#include\"string.h\"#include\"stdio.h\"#include\"malloc.h\"main(void){

char*src=\"hello,world\";char*dest=NULL;

dest=(char*)malloc(sizeof(char)*(strlen(src)+1));intlen=strlen(src);char*d=dest;

char*s=src+len-1;while(len--!=0)

*d++=*s--;*d='\\0';

printf(\"%s\}

1.简述一个Linux驱动程序的主要流程与功能。

2.请列举一个软件中时间换空间或者空间换时间的例子。voidswap(inta,intb){

intc;c=a;a=b;b=a;}

--->空优

voidswap(inta,intb){

a=a+b;b=a-b;a=a-b;}

6.请问一下程序将输出什么结果?char*RetMenory(void){

charp[]=“hellowworld”;returnp;}

voidTest(void){

char*str=NULL;str=RetMemory();printf(str);}

RetMenory执行完毕,p资源被回收,指向未知地址。返回地址,str的内容应是不可预测的,打印的应该是str的地址

写一个函数,它的原形是intcontinumax(char*outputstr,char*intputstr)功能:

在字符串中找出连续最长的数字串,并把这个串的长度返回,并把这个最长数字串付给其中一个函数参数outputstr所指内存。例如:\"abcd12345ed125ss1234567\"的首地址传给intputstr后,函数将返回

9,outputstr所指的值为1234567

intcontinumax(char*outputstr,char*inputstr){

char*in=inputstr,*out=outputstr,*temp,*final;

intcount=0,maxlen=0;

while(*in!='\\0'){

if(*in>47&&*in<58){

for(temp=in;*in>47&&*in<58;in++)count++;}elsein++;

if(maxlenmaxlen=count;count=0;final=temp;}}

for(inti=0;i*out=*final;out++;final++;}

*out='\\0';returnmaxlen;}

不用库函数,用C语言实现将一整型数字转化为字符串方法1:

intgetlen(char*s){intn;

for(n=0;*s!='\\0';s++)n++;returnn;}

voidreverse(chars[]){

intc,i,j;

for(i=0,j=getlen(s)-1;i}}

voiditoa(intn,chars[]){

inti,sign;

if((sign=n)<0)n=-n;i=0;

do{/*以反序生成数字*/

s[i++]=n%10+'0';/*getnextnumber*/}while((n/=10)>0);/*deletethenumber*/if(sign<0)s[i++]='-';

s[i]='\\0';reverse(s);}

方法2:

#includeusingnamespacestd;voiditochar(intnum);voiditochar(intnum){

inti=0;intj;

charstra[10];charstrb[10];while(num){

stra[i++]=num%10+48;num=num/10;}

stra[i]='\\0';

for(j=0;jstrb[j]=stra[i-j-1];}

strb[j]='\\0';

cout<intmain(){

intnum;cin>>num;itochar(num);return0;}

前几天面试,有一题想不明白,请教大家!typedefstruct{

inta:2;intb:2;intc:1;}test;testt;t.a=1;t.b=3;t.c=1;

printf(\"%d\printf(\"%d\printf(\"%d\谢谢!

t.a为01,输出就是1t.b为11,输出就是-1t.c为1,输出也是-1

3个都是有符号数int嘛。这是位扩展问题01111

编译器进行符号扩展

求组合数:求n个数(1....n)中k个数的组合....如:combination(5,3)

要求输出:3,2,1,532,531,521,432,431,421,321,#includeintpop(int*);intpush(int);

voidcombination(int,int);intstack[3]={0};top=-1;

intmain(){

intn,m;

printf(\"Inputtwonumbers:\\n\");

while((2!=scanf(\"%d%*c%d\){

fflush(stdin);

printf(\"Inputerror!Again:\\n\");}

combination(n,m);printf(\"\\n\");}

voidcombination(intm,intn){

inttemp=m;push(temp);while(1){

if(1==temp){

if(pop(&temp)&&stack[0]==n)//当栈底元素弹出&&为可能取的最小值,循环退出break;}

elseif(push(--temp)){

printf(\"%d%d%d\pop(&temp);}}}

intpush(inti){

stack[++top]=i;if(top<2)return0;else

return1;}

intpop(int*i){

*i=stack[top--];if(top>=0)return0;else

return1;}

1、用指针的方法,将字符串“ABCD1234efgh”前后对调显示#include#include#includeintmain(){

charstr[]=\"ABCD1234efgh\";intlength=strlen(str);char*p1=str;

char*p2=str+length-1;while(p1charc=*p1;*p1=*p2;*p2=c;++p1;--p2;}

printf(\"strnowis%s\\n\system(\"pause\");return0;}

2、有一分数序列:1/2,1/4,1/6,1/8……,用函数调用的方法,求此数列前20项的和

#includedoublegetValue(){

doubleresult=0;inti=2;

while(i<42){

result+=1.0/i;//一定要使用1.0做除数,不能用1,否则结果将自动转化成整数,即0.000000i+=2;}

returnresult;}

intmain(){

printf(\"resultis%f\\n\getValue());system(\"pause\");return0;}

Top

回复人:free131(白日?做梦!)()信誉:1002006-4-1710:18:33得分:0

?

有一个数组a[1000]存放0--1000;要求每隔二个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。以7个数为例:

{0,1,2,3,4,5,6,7}0-->1-->2(删除)-->3-->4-->5(删除)-->6-->7-->0(删除),如此循环直到最后一个数被删除。方法1:数组

#includeusingnamespacestd;#definenull1000

intmain(){

intarr[1000];

for(inti=0;i<1000;++i)arr[i]=i;intj=0;

intcount=0;

while(count<999){

while(arr[j%1000]==null)j=(++j)%1000;j=(++j)%1000;

while(arr[j%1000]==null)j=(++j)%1000;j=(++j)%1000;

while(arr[j%1000]==null)j=(++j)%1000;arr[j]=null;++count;}

while(arr[j]==null)j=(++j)%1000;

cout<#includeusingnamespacestd;#definenull0structnode{

intdata;node*next;};

intmain(){

node*head=newnode;head->data=0;head->next=null;node*p=head;

for(inti=1;i<1000;i++){

node*tmp=newnode;tmp->data=i;tmp->next=null;head->next=tmp;head=head->next;}

head->next=p;while(p!=p->next){

p->next->next=p->next->next->next;p=p->next->next;}

cout<data;return0;

}

方法3:通用算法#include

#defineMAXLINE1000//元素个数/*

MAXLINE元素个数a[]元素数组R[]指针场suffix下标

index返回最后的下标序号

values返回最后的下标对应的值start从第几个开始K间隔*/

intfind_n(inta[],intR[],intK,int&index,int&values,ints=0){intsuffix;

intfront_node,current_node;suffix=0;if(s==0){

current_node=0;

front_node=MAXLINE-1;}

else{

current_node=s;front_node=s-1;}

while(R[front_node]!=front_node){printf(\"%d\\n\R[front_node]=R[current_node];if(K==1){

current_node=R[front_node];continue;}

for(inti=0;ifront_node=R[front_node];}

current_node=R[front_node];}

index=front_node;values=a[front_node];return0;}

intmain(void){

inta[MAXLINE],R[MAXLINE],suffix,index,values,start,i,K;suffix=index=values=start=0;K=2;

for(i=0;iR[i-1]=0;

find_n(a,R,K,index,values,2);

printf(\"thevalueis%d,%d\\n\return0;}

试题:

voidtest2(){

charstring[10],str1[10];inti;

for(i=0;i<10;i++){

str1[i]='a';}

strcpy(string,str1);}

解答:对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string,str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;

str1不能在数组内结束:因为str1的存储为:{a,a,a,a,a,a,a,a,a,a},没有'\\0'(字符串结束符),所以不能结束

strcpy(char*s1,char*s2)他的工作原理是,扫描s2指向的内存,逐个字符付到s1所指向的内存,直到碰到'\\0',因为str1结尾没有'\\0',所以具有不确定性,不知道他后面还会付什么东东。正确应如下voidtest2(){

charstring[10],str1[10];inti;

for(i=0;i<9;i++){

str1[i]='a'+i;//把abcdefghi赋值给字符数组}

str[i]='\\0';//加上结束符

strcpy(string,str1);}

第二个code题是实现strcmp

intStrCmp(constchar*str1,constchar*str2)做是做对了,没有抄搞,比较乱

intStrCmp(constchar*str1,constchar*str2){

assert(str1&&srt2);

while(*str1&&*str2&&*str1==*str2){str1++,str2++;}

if(*str1&&*str2)return(*str1-*str2);

elseif(*str1&&*str2==0)return1;

elseif(*str1==0&&*str2)return-1;else

return0;}

intStrCmp(constchar*str1,constchar*str2){

//省略判断空指针(自己保证)

while(*str1&&*str1++==*str2++);return*str1-*str2;}

第三个code题是实现子串定位

intFindSubStr(constchar*MainStr,constchar*SubStr)做是做对了,没有抄搞,比较乱

intMyStrstr(constchar*MainStr,constchar*SubStr){

constchar*p;constchar*q;

constchar*u=MainStr;

//assert((MainStr!=NULL)&&(SubStr!=NULL));//用断言对输入进行判断

while(*MainStr)//内部进行递增{

p=MainStr;q=SubStr;

while(*q&&*p&&*p++==*q++);

if(!*q){

returnMainStr-u+1;//MainStr指向当前起始位,u指向}

MainStr++;}

return-1;}

分析:

intarr[]={6,7,8,9,10};int*ptr=arr;*(ptr++)+=123;

printf(“%d%d”,*ptr,*(++ptr));输出:88

过程:对于*(ptr++)+=123;先做加法6+123,然后++,指针指向7;对于printf(“%d%d”,*ptr,*(++ptr));从后往前执行,指针先++,指向8,然后输出8,紧接着再输出8

华为全套完整试题高级题

6、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后删除。slnodetype*Delete(slnodetype*Head,intkey){}中if(Head->number==key){

Head=Pointer->next;free(Pointer);break;}

Back=Pointer;

Pointer=Pointer->next;if(Pointer->number==key){

Back->next=Pointer->next;free(Pointer);break;}

voiddelete(Node*p){

if(Head=Node)while(p)}

有一个16位的整数,每4位为一个数,写函数求他们的和。解释:

整数1101010110110111和1101+0101+1011+0111

感觉应该不难,当时对题理解的不是很清楚,所以写了一个函数,也不知道对不对。疑问:

既然是16位的整数,1101010110110111是2进制的,那么函数参数怎么定义呢,请大虾指教。

答案:用十进制做参数,计算时按二进制考虑。

/*n就是16位的数,函数返回它的四个部分之和*/charSumOfQuaters(unsignedshortn){

charc=0;inti=4;do{

c+=n&15;n=n>>4;}while(--i);returnc;}

有1,2,....一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数.(华为)#includeint{intintint

main()

a[]={10,6,9,5,2,8,4,7,1,3};len=sizeof(a)/sizeof(int);temp;

for(inti=0;itemp=a[a[i]-1];a[a[i]-1]=a[i];a[i]=temp;if(a[i]==i+1)

i++;}

for(intj=0;j(慧通)

1写出程序把一个链表中的接点顺序倒排typedefstructlinknode{

intdata;

structlinknode*next;}node;

//将一个链表逆置

node*reverse(node*head){

node*p,*q,*r;p=head;q=p->next;while(q!=NULL){

r=q->next;q->next=p;p=q;q=r;}

head->next=NULL;head=p;

returnhead;}

2写出程序删除链表中的所有接点voiddel_all(node*head){

node*p;

while(head!=NULL){

p=head->next;free(head);head=p;}

cout<<\"释放空间成功!\"<}

3两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串

voidinsert(char*s,char*t,inti){

char*q=t;char*p=s;

if(q==NULL)return;while(*p!='\\0'){

p++;}

while(*q!=0){

*p=*q;p++;q++;}

*p='\\0';}

分析下面的代码:char*a=\"hello\";char*b=\"hello\";if(a==b)

printf(\"YES\");else

printf(\"NO\");

这个简单的面试题目,我选输出no(对比的应该是指针地址吧),可在VC是YES在C是NO

lz的呢,是一个常量字符串。位于静态存储区,它在程序生命期内恒定不变。如果编译器优化的话,会有可能a和b同时指向同一个hello的。则地址相同。如果编译器没有优化,那么就是两个不同的地址,则不同

写一个函数,功能:完成内存之间的拷贝memcpysourcecode:

270void*memcpy(void*dst,constvoid*src,unsignedintlen)271{

272registerchar*d;273registerchar*s;27

275if(len==0)276returndst;

277

278if(is_overlap(dst,src,len,len))

279complain3(\"memcpy\dst,src,len);280

281if(dst>src){

282d=(char*)dst+len-1;283s=(char*)src+len-1;284while(len>=4){285*d--=*s--;286*d--=*s--;287*d--=*s--;288*d--=*s--;2len-=4;290}

291while(len--){292*d--=*s--;293}

294}elseif(dst=4){298*d++=*s++;299*d++=*s++;300*d++=*s++;301*d++=*s++;302len-=4;303}

304while(len--){305*d++=*s++;306}307}

308returndst;309}

公司考试这种题目主要考你编写的代码是否考虑到各种情况,是否安全(不会溢出)

各种情况包括:

1、参数是指针,检查指针是否有效

2、检查复制的源目标和目的地是否为同一个,若为同一个,则直接跳出3、读写权限检查

4、安全检查,是否会溢出

memcpy拷贝一块内存,内存的大小你告诉它strcpy是字符串拷贝,遇到'\\0'结束

/*memcpy───拷贝不重叠的内存块*/

voidmemcpy(void*pvTo,void*pvFrom,size_tsize){

void*pbTo=(byte*)pvTo;

void*pbFrom=(byte*)pvFrom;

ASSERT(pvTo!=NULL&&pvFrom!=NULL);//检查输入指针的有效性

ASSERT(pbTo>=pbFrom+size||pbFrom>=pbTo+size);//检查两个指针指向的内存是否重叠while(size-->0)

*pbTo++==*pbFrom++;return(pvTo);}

华为面试题:怎么判断链表中是否有环?boolCircleInList(Link*pHead){

if(pHead==NULL||pHead->next==NULL)//无节点或只有一个节点并且无自环return(false);

if(pHead->next==pHead)//自环return(true);

Link*pTemp1=pHead;//step1

Link*pTemp=pHead->next;//step2

while(pTemp!=pTemp1&&pTemp!=NULL&&pTemp->next!=NULL){

pTemp1=pTemp1->next;

pTemp=pTemp->next->next;}

if(pTemp==pTemp1)return(true);return(false);}

两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串

voidinsert(char*s,char*t,inti){

memcpy(&s[strlen(t)+i],&s[i],strlen(s)-i);memcpy(&s[i],t,strlen(t));s[strlen(s)+strlen(t)]='\\0';}

1。编写一个C函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的。

char*search(char*cpSource,charch){

char*cpTemp=NULL,*cpDest=NULL;intiTemp,iCount=0;while(*cpSource){

if(*cpSource==ch){

iTemp=0;

cpTemp=cpSource;while(*cpSource==ch)++iTemp,++cpSource;if(iTemp>iCount)

iCount=iTemp,cpDest=cpTemp;if(!*cpSource)break;}

++cpSource;}

returncpDest;}

2。请编写一个C函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值。

intsearch(char*cpSource,intn,charch){inti;

for(i=0;i一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?

将这个指针指向的next节点值copy到本节点,将next指向next->next,并随后删除原next指向的节点。

#includevoidfoo(intm,intn){

printf(\"m=%d,n=%d\\n\m,n);}

intmain(){

intb=3;

foo(b+=3,++b);printf(\"b=%d\\n\b);return0;}

输出:m=7,n=4,b=7(VC6.0)

这种方式和编译器中得函数调用关系相关即先后入栈顺序。不过不同编译器得处理不同。也是因为C标准中对这种方式说明为未定义,所以各个编译器厂商都有自己得理解,所以最后产生得结果完全不同。

因为这样,所以遇见这种函数,我们首先要考虑我们得编译器会如何处理这样得函数,其次看函数得调用方式,不同得调用方式,可能产生不同得结果。最后是看编译器优化。

2.写一函数,实现删除字符串str1中含有的字符串str2.

第二个就是利用一个KMP匹配算法找到str2然后删除(用链表实现的话,便捷于数组)

/*雅虎笔试题(字符串操作)

给定字符串A和B,输出A和B中的最大公共子串。比如A=\"aocdfe\"B=\"pmcdfa\"则输出\"cdf\"*/

//Author:azhen#include#include#include

char*commanstring(charshortstring[],charlongstring[]){

inti,j;

char*substring=malloc(256);

if(strstr(longstring,shortstring)!=NULL)//如果……,那么返回shortstring

returnshortstring;

for(i=strlen(shortstring)-1;i>0;i--)//否则,开始循环计算{

for(j=0;j<=strlen(shortstring)-i;j++){memcpy(substring,&shortstring[j],i);

substring[i]='\\0';

if(strstr(longstring,substring)!=NULL)returnsubstring;}}

returnNULL;}

main(){

char*str1=malloc(256);char*str2=malloc(256);char*comman=NULL;gets(str1);gets(str2);

if(strlen(str1)>strlen(str2))//将短的字符串放前面comman=commanstring(str2,str1);else

comman=commanstring(str1,str2);

printf(\"thelongestcommanstringis:%s\\n\comman);}

11.写一个函数比较两个字符串str1和str2的大小,若相等返回0,若str1大于

str2返回1,若str1小于str2返回-1

intstrcmp(constchar*src,constchar*dst){

intret=0;

while(!(ret=*(unsignedchar*)src-*(unsignedchar*)dst)&&*dst){

++src;++dst;}

if(ret<0)ret=-1;

elseif(ret>0)ret=1;

return(ret);

}

3,求1000!的未尾有几个0(用素数相乘的方法来做,如72=2*2*2*3*3);求出1->1000里,能被5整除的数的个数n1,能被25整除的数的个数n2,能被125整除的数的个数n3,能被625整除的数的个数n4.

1000!末尾的零的个数=n1+n2+n3+n4;#include#defineNUM1000

intfind5(intnum){intret=0;

while(num%5==0){num/=5;ret++;}

returnret;}

intmain(){intresult=0;inti;

for(i=5;i<=NUM;i+=5){

result+=find5(i);}

printf(\"thetotalzeronumberis%d\\n\return0;}

1.有双向循环链表结点定义为:structnode{intdata;

structnode*front,*next;};

有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除

BOOLDeteleNode(Node*pHeader,DataTypeValue){

if(pHeader==NULL)return;BOOLbRet=FALSE;

Node*pNode=pHead;while(pNode!=NULL){

if(pNode->data==Value){

if(pNode->front==NULL){

pHeader=pNode->next;pHeader->front=NULL;}else{

if(pNode->next!=NULL){

pNode->next->front=pNode->front;}

pNode->front->next=pNode->next;}

Node*pNextNode=pNode->next;deletepNode;

pNode=pNextNode;

bRet=TRUE;

//不要break或return,删除所有}else{

pNode=pNode->next;}}

returnbRet;}

voidDE(Node*pHeadA,Node*pHeadB){

if(pHeadA==NULL||pHeadB==NULL){

return;}

Node*pNode=pHeadA;while(pNode!=NULL)

{

if(DeteleNode(pHeadB,pNode->data)){

if(pNode->front==NULL){

pHeadA=pNode->next;pHeadA->front=NULL;}else{

pNode->front->next=pNode->next;if(pNode->next!=NULL){

pNode->next->front=pNode->front;}}

Node*pNextNode=pNode->next;deletepNode;

pNode=pNextNode;}else{

pNode=pNode->next;}}}

2.编程实现:找出两个字符串中最大公共子字符串,如\"abccade\的最大子串为\"cad\"

intGetCommon(char*s1,char*s2,char**r1,char**r2){

intlen1=strlen(s1);intlen2=strlen(s2);intmaxlen=0;

for(inti=0;ifor(intj=0;jif(s1[i]==s2[j]){

intas=i,bs=j,count=1;

while(as+1if(count>maxlen){

maxlen=count;*r1=s1+i;*r2=s2+j;}}}}

3.编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列库函数char*test3(longnum){

char*buffer=(char*)malloc(11);buffer[0]='0';buffer[1]='x';buffer[10]='\\0';

char*temp=buffer+2;for(inti=0;i<8;i++){

temp[i]=(char)(num<<4*i>>28);

temp[i]=temp[i]>=0?temp[i]:temp[i]+16;

temp[i]=temp[i]<10?temp[i]+48:temp[i]+55;}

returnbuffer;}

输入N,打印N*N矩阵比如N=3,打印:1234765

N=4,打印:12341213145111615610987解答:

1#defineN15

ints[N][N];voidmain(){

intk=0,i=0,j=0;inta=1;

for(;k<(N+1)/2;k++){

while(jk-1)s[i][j--]=a++;i--;j++;while(i>k)s[i--][j]=a++;i++;j++;}

for(i=0;ifor(j=0;j2defineMAX_N100

intmatrix[MAX_N][MAX_N];

/*

*(x,y):第一个元素的坐标*start:第一个元素的值*n:矩阵的大小*/

voidSetMatrix(intx,inty,intstart,intn){inti,j;

if(n<=0)//递归结束条件return;

if(n==1){//矩阵大小为1时matrix[x][y]=start;return;}

for(i=x;ifor(j=y;jx;i--)//底部matrix[y+n-1][i]=start++;

for(j=y+n-1;j>y;j--)//左部matrix[j][x]=start++;

SetMatrix(x+1,y+1,start,n-2);//递归}

voidmain(){inti,j;intn;

scanf(\"%d\&n);

SetMatrix(0,0,1,n);//打印螺旋矩阵

for(i=0;iprintf(\"%4d\matrix[i][j]);printf(\"\\n\");}}

斐波拉契数列递归实现的方法如下:intFunct(intn){

if(n==0)return1;if(n==1)return1;

retrurnFunct(n-1)+Funct(n-2);}

请问,如何不使用递归,来实现上述函数?请教各位高手!

解答:intFunct(intn)//n为非负整数{

inta=0;intb=1;intc;

if(n==0)c=1;

elseif(n==1)c=1;

elsefor(inti=2;i<=n;i++)//应该n从2开始算起{

c=a+b;a=b;b=c;

}

returnc;}

解答:

现在大多数系统都是将低字位放在前面,而结构体中位域的申明一般是先声明高位。

100的二进制是001100100低位在前高位在后001----s3100----s2100----s1

所以结果应该是1

如果先申明的在低位则:001----s1100----s2100----s3结果是4

1、原题跟little-endian,big-endian没有关系

2、原题跟位域的存储空间分配有关,到底是从低字节分配还是从高字节分配,从DevC++和VC7.1上看,都是从低字节开始分配,并且连续分配,中间不空,不像谭的书那样会留空位

3、原题跟编译器有关,编译器在未用堆栈空间的默认值分配上有所不同,DevC++未用空间分配为

01110111b,VC7.1下为11001100b,所以在DevC++下的结果为5,在VC7.1下为1。

注:PC一般采用little-endian,即高高低低,但在网络传输上,一般采用big-endian,即高低低高,华为是做网络的,所以可能考虑big-endian模式,这样输出结果可能为4

判断一个字符串是不是回文

intIsReverseStr(char*aStr){

inti,j;

intfound=1;if(aStr==NULL)return-1;

j=strlen(aStr);for(i=0;iif(*(aStr+i)!=*(aStr+j-i-1)){

found=0;

break;}

returnfound;}

Josephu问题为:设编号为1,2,…n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

数组实现:

#include#includeintJosephu(intn,intm){

intflag,i,j=0;

int*arr=(int*)malloc(n*sizeof(int));for(i=0;ifor(i=1;iflag=0;

while(flagif(j==n)j=0;if(arr[j])++flag;++j;}

arr[j-1]=0;

printf(\"第%4d个出局的人是:%4d号\\n\i,j);}

free(arr);returnj;}

intmain(){

intn,m;

scanf(\"%d%d\&n,&m);

printf(\"最后胜利的是%d号!\\n\Josephu(n,m));system(\"pause\");return0;}

链表实现:

#include#includetypedefstructNode{

intindex;

structNode*next;}JosephuNode;

intJosephu(intn,intm){

inti,j;

JosephuNode*head,*tail;

head=tail=(JosephuNode*)malloc(sizeof(JosephuNode));for(i=1;itail->index=i;

tail->next=(JosephuNode*)malloc(sizeof(JosephuNode));tail=tail->next;}

tail->index=i;tail->next=head;

for(i=1;tail!=head;++i){

for(j=1;jtail=head;

head=head->next;}

tail->next=head->next;

printf(\"第%4d个出局的人是:%4d号\\n\i,head->index);free(head);

head=tail->next;}

i=head->index;free(head);returni;}

intmain(){

intn,m;

scanf(\"%d%d\&n,&m);

printf(\"最后胜利的是%d号!\\n\Josephu(n,m));system(\"pause\");return0;

}

已知strcpy函数的原型是:

char*strcpy(char*strDest,constchar*strSrc);1.不调用库函数,实现strcpy函数。2.解释为什么要返回char*。解说:

1.strcpy的实现代码

char*strcpy(char*strDest,constchar*strSrc){

if((strDest==NULL)||(strSrc==NULL))file://[/1]throw\"Invalidargument(s)\";//[2]

char*strDestCopy=strDest;file://[/3]

while((*strDest++=*strSrc++)!='\\0');file://[/4]returnstrDestCopy;}

错误的做法:[1]

(A)不检查指针的有效性,说明答题者不注重代码的健壮性。

(B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char*转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。

(C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。[2]

(A)returnnewstring(\"Invalidargument(s)\");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。

(B)return0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。[3]

(A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。[4]

(A)循环写成while(*strDest++=*strSrc++);,同[1](B)。

(B)循环写成while(*strSrc!='\\0')*strDest++=*strSrc++;,说明答

题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'\\0'。

预处理器(Preprocessor)

1.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

#defineSECONDS_PER_YEAR(60*60*24*365)UL我在这想看到几件事情:

1).#define语法的基本知识(例如:不能以分号结束,括号的使用,等等)2).懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。

3).意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。

4).如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。

2.写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。

#defineMIN(A,B)((A)<=(B)(A):(B))这个测试是为下面的目的而设的:

1).标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。2).三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。3).懂得在宏中小心地把参数用括号括起来

4).我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?

least=MIN(*p++,b);

3.预处理器标识#error的目的是什么?

如果你不知道答案,请看参考文献1。这问题对区分一个正常的伙计和一个书呆子是很有用的。只有书呆子才会读C语言课本的附录去找出象这种问题的答案。当然如果你不是在找一个书呆子,那么应试者最好希望自己不要知道答案。

死循环(Infiniteloops)

4.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?

这个问题用几个解决方案。我首选的方案是:while(1){}

一些程序员更喜欢如下方案:for(;;){}

这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的

基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。第三个方案是用gotoLoop:...

gotoLoop;

应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。数据声明(Datadeclarations)

5.用变量a给出下面的定义a)一个整型数(Aninteger)

b)一个指向整型数的指针(Apointertoaninteger)

c)一个指向指针的的指针,它指向的指针是指向一个整型数(Apointertoapointertoaninteger)

d)一个有10个整型数的数组(Anarrayof10integers)

e)一个有10个指针的数组,该指针是指向一个整型数的(Anarrayof10pointerstointegers)

f)一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(Apointertoafunctionthattakesanintegerasanargumentandreturnsaninteger)h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(Anarrayoftenpointerstofunctionsthattakeanintegerargumentandreturnaninteger)答案是:

a)inta;//Aninteger

b)int*a;//Apointertoaninteger

c)int**a;//Apointertoapointertoanintegerd)inta[10];//Anarrayof10integers

e)int*a[10];//Anarrayof10pointerstointegersf)int(*a)[10];//Apointertoanarrayof10integers

g)int(*a)(int);//Apointertoafunctionathattakesanintegerargumentandreturnsaninteger

h)int(*a[10])(int);//Anarrayof10pointerstofunctionsthattakeanintegerargumentandreturnaninteger

人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。

但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道

所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢?

Static

6.关键字static的作用是什么?

这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:

1).在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

2).在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。3).在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被在声明它的模块的本地范围内使用。

大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。

Const

7.关键字const是什么含意?

我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。去年DanSaks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:EmbeddedSystemsProgramming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)如果应试

者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?constinta;intconsta;constint*a;int*consta;

intconst*aconst;

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:

1).关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)

2).通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

3).合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。Volatile

8.关键字volatile有什么含意并给出三个不同的例子。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1).并行设备的硬件寄存器(如:状态寄存器)

2).一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables)3).多线程应用中被几个任务共享的变量回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。1).一个参数既可以是const还可以是volatile吗?解释为什么。2).一个指针可以是volatile吗?解释为什么。3).下面的函数有什么错误:

intsquare(volatileint*ptr){

return*ptr**ptr;}

下面是答案:

1).是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。2).是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

3).这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:intsquare(volatileint*ptr){

inta,b;a=*ptr;b=*ptr;returna*b;}

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:longsquare(volatileint*ptr){

inta;a=*ptr;returna*a;}

位操作(Bitmanipulation)

9.嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。在以上两个操作中,要保持其它位不变。

对这个问题有三种基本的反应

1).不知道如何下手。该被面者从没做过任何嵌入式系统的工作。

2).用bitfields。Bitfields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到Infineon为其较复杂的通信芯片写的驱动程序,它用到了bitfields因此完全对我无用,因为我的编译器用其它的方式来实现bitfields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。

3).用#defines和bitmasks操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:#defineBIT3(0x1<<3)staticinta;

voidset_bit3(void){

a|=BIT3;}

voidclear_bit3(void){

a&=~BIT3;}

一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。

访问固定的内存位置(Accessingfixedmemorylocations)

10.嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。

这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:int*ptr;

ptr=(int*)0x67a9;*ptr=0xaa55;

一个较晦涩的方法是:

*(int*const)(0x67a9)=0xaa55;

即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。

中断(Interrupts)

11.中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。

__interruptdoublecompute_area(doubleradius){

doublearea=PI*radius*radius;printf(\"Area=%f\area);returnarea;}

这个函数有太多的错误了,以至让人不知从何说起了:

1).ISR不能返回一个值。如果你不懂这个,那么你不会被雇用的。

2).ISR不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。3).在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。4).与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

代码例子(Codeexamples)

12.下面的代码输出是什么,为什么?

voidfoo(void){

unsignedinta=6;intb=-20;

(a+b>6)puts(\">6\"):puts(\"<=6\");}

这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是“>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。

13.评价下面的代码片断:

unsignedintzero=0;

unsignedintcompzero=0xFFFF;/*1'scomplementofzero*/

对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:

unsignedintcompzero=~0;

这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧…

动态内存分配(Dynamicmemoryallocation)

14.尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?

这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(主要是P.J.Plauger,他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:下面的代码片段的输出是什么,为什么?

char*ptr;

if((ptr=(char*)malloc(0))==NULL)puts(\"Gotanullpointer\");else

puts(\"Gotavalidpointer\");

这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是“Gotavalidpointer”。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。

Typedef

15.Typedef在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:#definedPSstructs*typedefstructs*tPS;

以上两种情况的意图都是要定义dPS和tPS作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:dPSp1,p2;tPSp3,p4;

第一个扩展为

structs*p1,p2;

上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3和p4两个指针。

晦涩的语法

16.C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?

inta=5,b=7,c;c=a+++b;

这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:c=a+++b;

因此,这段代码持行后a=6,b=7,c=12。

如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题

C++

1.以下三条输出语句分别输出什么?[C易]charstr1[]=\"abc\";charstr2[]=\"abc\";

constcharstr3[]=\"abc\";constcharstr4[]=\"abc\";constchar*str5=\"abc\";constchar*str6=\"abc\";

cout<cout<2.非C++内建型别A和B,在哪几种情况下B能隐式转化为A?[C++中等]答:

a.classB:publicA{……}//B公有继承自A,可以是间接继承的b.classB{operatorA();}//B实现了隐式转化为A的转化

c.classA{A(constB&);}//A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数

d.A&operator=(constA&);//赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个

3.以下代码中的两个sizeof用法有问题吗?[C易]

voidUpperCase(charstr[])//将str中的小写字母转换成大写字母{

for(size_ti=0;icharstr[]=\"aBcDe\";

cout<<\"str字符长度为:\"<4.以下代码有什么问题?[C难]

voidchar2Hex(charc)//将字符以16进制表示{

charch=c/0x10+'0';if(ch>'9')ch+=('A'-'9'-1);charcl=c%0x10+'0';if(cl>'9')cl+=('A'-'9'-1);cout<charstr[]=\"Ilove中国\";

for(size_ti=0;i5.以下代码有什么问题?[C++易]structTest{

Test(int){}Test(){}voidfun(){}};

voidmain(void){

Testa(1);a.fun();Testb();b.fun();}

6.以下代码有什么问题?[C++易]cout<<(true?1:\"1\")<7.以下代码能够编译通过吗,为什么?[C++易]unsignedintconstsize1=2;charstr1[size1];

unsignedinttemp=0;cin>>temp;

unsignedintconstsize2=temp;charstr2[size2];

8.以下代码中的输出语句输出0吗,为什么?[C++易]structCLS{

intm_i;

CLS(inti):m_i(i){}CLS(){

CLS(0);}};

CLSobj;

cout<9.C++中的空类,默认产生哪些类成员函数?[C++易]答:

classEmpty{

public:

Empty();//缺省构造函数

Empty(constEmpty&);//拷贝构造函数~Empty();//析构函数

Empty&operator=(constEmpty&);//赋值运算符Empty*operator&();//取址运算符

constEmpty*operator&()const;//取址运算符const};

10.以下两条输出语句分别输出什么?[C++难]

floata=1.0f;

cout<<(int)a<cout<cout<<(int)b<cout<array.push_back(1);array.push_back(2);array.push_back(3);

for(vector::size_typei=array.size()-1;i>=0;--i)//反向遍历array数组{

cout<12.以下代码有什么问题?[STL易]typedefvectorIntArray;IntArrayarray;

array.push_back(1);array.push_back(2);array.push_back(2);array.push_back(3);

//删除array数组中所有的2

for(IntArray::iteratoritor=array.begin();itor!=array.end();++itor){

if(2==*itor)array.erase(itor);}

13.写一个函数,完成内存之间的拷贝。[考虑问题是否全面]答:

void*mymemcpy(void*dest,constvoid*src,size_tcount){

char*pdest=static_cast(dest);

constchar*psrc=static_cast(src);

if(pdest>psrc&&pdestfor(size_ti=count-1;i!=-1;--i)pdest[i]=psrc[i];}else

{

for(size_ti=0;ireturndest;}

intmain(void){

charstr[]=\"01234567\";mymemcpy(str+1,str+0,9);cout<本试题仅用于考查C++/C程序员的基本编程技能。内容限于C++/C常用语法,不涉及数据结构、算法以及深奥的语法。考试成绩能反映出考生的编程质量以及对C++/C的理解程度,但不能反映考生的智力和软件开发能力。笔试时间90分钟。请考生认真答题,切勿轻视。

一、请填写BOOL,float,指针变量与“零值”比较的if语句。(10分)提示:这里“零值”可以是0,0.0,FALSE或者“空指针”。例如int变量n与“零值”比较的if语句为:if(n==0)if(n!=0)以此类推。

请写出BOOLflag与“零值”比较的if语句:

请写出floatx与“零值”比较的if语句:

请写出char*p与“零值”比较的if语句:

二、以下为WindowsNT下的32位C++程序,请计算sizeof的值(10分)

charstr[]=“Hello”;char*p=str;intn=10;请计算sizeof(str)=

sizeof(p)=

sizeof(n)=

voidFunc(charstr[100]){请计算sizeof(str)=}

void*p=malloc(100);请计算sizeof(p)=

三、简答题(25分)

1、头文件中的ifndef/define/endif干什么用?

2、#include和#include“filename.h”有什么区别?

3、const有什么用途?(请至少说明两种)

4、在C++程序中调用被C编译器编译后的函数,为什么要加extern“C”声明?

5、请简述以下两个for循环的优缺点

//第一个for(i=0;i{

if(condition)DoSomething();else

DoOtherthing();}

//第二个if(condition){for(i=0;iDoSomething();}else{for(i=0;iDoOtherthing();}优点:

缺点:

优点:

缺点:

四、有关内存的思考题(20分)

voidGetMemory(char*p){

p=(char*)malloc(100);}

voidTest(void){

char*str=NULL;GetMemory(str);strcpy(str,\"helloworld\");printf(str);}

请问运行Test函数会有什么样的结果?答:

char*GetMemory(void){

charp[]=\"helloworld\";returnp;}

voidTest(void){

char*str=NULL;str=GetMemory();printf(str);}

请问运行Test函数会有什么样的结果?答:

VoidGetMemory2(char**p,intnum){

*p=(char*)malloc(num);}

voidTest(void){

char*str=NULL;GetMemory(&str,100);strcpy(str,\"hello\");printf(str);}

请问运行Test函数会有什么样的结果?答:

voidTest(void){

char*str=(char*)malloc(100);strcpy(str,“hello”);free(str);if(str!=NULL){

strcpy(str,“world”);printf(str);}}

请问运行Test函数会有什么样的结果?答:

五、编写strcpy函数(10分)已知strcpy函数的原型是

char*strcpy(char*strDest,constchar*strSrc);

其中strDest是目的字符串,strSrc是源字符串。

(1)不调用C++/C的字符串库函数,请编写函数strcpy

(2)strcpy能把strSrc的内容复制到strDest,为什么还要char*类型的返回值?

六、编写类String的构造函数、析构函数和赋值函数(25分)已知类String的原型为:classString{public:

String(constchar*str=NULL);//普通构造函数String(constString&other);//拷贝构造函数~String(void);//析构函数

String&operate=(constString&other);//赋值函数private:

char*m_data;//用于保存字符串};

请编写String的上述4个函数。

附录C:C++/C试题的答案与评分标准

一、请填写BOOL,float,指针变量与“零值”比较的if语句。(10分)

请写出BOOLflag与“零值”比较的if语句。(3分)标准答案:if(flag)

if(!flag)

如下写法均属不良风格,不得分。

Copyright © 2019- zrrp.cn 版权所有 赣ICP备2024042808号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务