版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、软件工程师笔试题(C/C+)2008-03-25 18:19预处理器(Preprocessor)1. 用预处理理指令#deefine 声明一个常常数,用以表表明1年中有多少少秒(忽略闰闰年问题)#definee SECOONDS_PPER_YEEAR (660 * 660 * 224 * 3365)ULL 我在这想看到几几件事情: 1). #deefine 语法的基本本知识(例如如:不能以分分号结束,括括号的使用,等等等) 2). 懂得预预处理器将为为你计算常数数表达式的值值,因此,直直接写出你是是如何计算一一年中有多少少秒而不是计计算出实际的的值,是更清清晰而没有代代价的。 3). 意识到到
2、这个表达式式将使一个116位机的整整型数溢出-因此要用到到长整型符号号L,告诉编译译器这个常数数是的长整型型数。 4). 如果你你在你的表达达式中用到UUL(表示无无符号长整型型),那么你你有了一个好好的起点。记记住,第一印印象很重要。2. 写一个标准宏MIN,这个个宏输入两个个参数并返回回较小的一个个。#definee MIN(A,B) (A) = (BB) (A) : (BB) 这个测试是为下下面的目的而而设的: 1). 标识#definne在宏中应应用的基本知知识。这是很很重要的,因因为直到嵌入入(inlinne)操作符符变为标准CC的一部分,宏宏是方便产生生嵌入代码的的唯一方法,对对于
3、嵌入式系系统来说,为为了能达到要要求的性能,嵌嵌入代码经常常是必须的方方法。 2). 三重条条件操作符的的知识。这个个操作符存在在C语言中的原原因是它使得得编译器能产产生比if-then-else更更优化的代码码,了解这个个用法是很重重要的。 3). 懂得在在宏中小心地地把参数用括括号括起来 4). 我也用用这个问题开开始讨论宏的的副作用,例例如:当你写写下面的代码码时会发生什什么事? least = MIN(*p+, b);3. 预处理器器标识#errror的目目的是什么?如果你不知道答答案,请看参参考文献1。这问题对对区分一个正正常的伙计和和一个书呆子子是很有用的的。只有书呆呆子才会读CC
4、语言课本的的附录去找出出象这种 问题的答案。当当然如果你不不是在找一个个书呆子,那那么应试者最最好希望自己己不要知道答答案。死循环(Inffinitee loopps)4. 嵌入式系系统中经常要要用到无限循循环,你怎么么样用C编写死循环环呢?这个问题用几个个解决方案。我我首选的方案案是: while(11) 一些程序员更喜喜欢如下方案案: for(;) 这个实现方式让让我为难,因因为这个语法法没有确切表表达到底怎么么回事。如果果一个应试者者给出这个作作为方案,我我将用这个作作为一个机会会去探究他们们这样做的 基本原理。如果果他们的基本本答案是:我被教着这这样做,但从从没有想到过过为什么。这会给
5、我留留下一个坏印印象。 第三个方案是用用 gotoo Loop: . goto Looop; 应试者如给出上上面的方案,这这说明或者他他是一个汇编编语言程序员员(这也许是是好事)或者者他是一个想想进入新领域域的BASIIC/FORRTRAN程程序员。数据声明(Daata deeclaraationss) 5. 用变量aa给出下面的的定义a) 一个整型型数(An integger) b) 一个指向向整型数的指指针(A ppointeer to an inntegerr) c) 一个指向向指针的的指指针,它指向向的指针是指指向一个整型型数(A ppointeer to a poiinter to
6、ann inteeger) d) 一个有110个整型数数的数组(AAn arrray off 10 iintegeers) e) 一个有110个指针的的数组,该指指针是指向一一个整型数的的(An aarray of 100 poinnters to inntegerrs) f) 一个指向向有10个整型数数数组的指针针(A poointerr to aan arrray off 10 iintegeers) g) 一个指向向函数的指针针,该函数有有一个整型参参数并返回一一个整型数(A pointer to a function that takes an integer as an argume
7、nt and returns an integer) h) 一个有110个指针的的数组,该指指针指向一个个函数,该函函数有一个整整型参数并返返回一个整型型数( Ann arraay of ten ppointeers too funcctionss thatt takee an iintegeer arggumentt and returrn an integger )答案是: a) int a; / An iintegeer b) int *a; / A ppointeer to an inntegerr c) int *a; / A pointter too a poointerr to
8、aan intteger d) int a10; / An arrray oof 10 integgers e) int *a100; / An aarray of 100 poinnters to inntegerrs f) int (*a)10; / A pointter too an aarray of 100 inteegers g) int (*a)(int); / AA poinnter tto a ffunctiion a that takess an iintegeer arggumentt and returrns ann inteeger h) int (*a110)(ii
9、nt); / Ann arraay of 10 poointerrs to functtions that take an inntegerr arguument and rreturnn an iintegeer 人们经常声称这这里有几个问问题是那种要要翻一下书才才能回答的问问题,我同意意这种说法。当当我写这篇文文章时,为了了确定语法的的正确性,我我的确查了一一下书。 但是当我被面试试的时候,我我期望被问到到这个问题(或或者相近的问问题)。因为为在被面试的的这段时间里里,我确定我我知道这个问问题的答案。应应试者如果不不知道 所有的答案(或或至少大部分分答案),那那么也就没有有为这次面试试做准
10、备,如如果该面试者者没有为这次次面试做准备备,那么他又又能为什么出出准备呢?Static6. 关键字sstaticc的作用是什什么?这个简单的问题题很少有人能能回答完全。在在C语言中,关关键字staticc有三个明显显的作用: 1). 在函数数体,一个被被声明为静态态的变量在这这一函数被调调用过程中维维持其值不变变。 2). 在模块块内(但在函函数体外),一一个被声明为为静态的变量量可以被模块块内所用函数数访问,但不不能被模块外外其它函数访访问。它是一一个本地的全全局变量。 3). 在模块块内,一个被被声明为静态态的函数只可可被这一模块块内的其它函函数调用。那那就是,这个个函数被限制制在声明它
11、的的模块的本地地范围内使用用。 大多数应试者能能正确回答第第一部分,一一部分能正确确回答第二部部分,同是很很少的人能懂懂得第三部分分。这是一个个应试者的严严重的缺点,因因为他显然不不懂得本地化化数据和代码码范围的好处处和重要性。Const 7关键字coonst是什什么含意?我只要一听到被被面试者说:consst意味着常常数,我就知道道我正在和一一个业余者打打交道。去年年Dan SSaks已经经在他的文章章里完全概括括了consst的所有用用法,因此EESP(译者者:Embeedded Systeems Prrogrammming)的每一位读读者应该非常常熟悉connst能做什什么和不能做做什么
12、.如果你从没没有读到那篇篇文章,只要要能说出coonst意味味着只读就可以了。尽尽管这个答案案不是完全的的答案,但我我接受它作为为一个正确的的答案。(如如果你想知道道更详细的答答案,仔细读读一下Sakks的文章吧吧。)如果应应试者能正确确回答这个问问题,我将问问他一个附加加的问题:下下面的声明都都是什么意思思?const iint a; int connst a; const iint *aa; int * cconst a; int connst * a connst;前两个的作用是是一样,a是一个常整整型数。第三三个意味着aa是一个指向向常整型数的的指针(也就就是,整型数数是不可修改改的,
13、但指针针可以)。第第四个意思aa是一个指向向整型数的常常指针(也就就是说,指针针指向的整型型数是可以修修改的,但指指针是不可修修改的)。最最后一个意味味着a是一个指向向常整型数的的常指针(也也就是说,指指针指向的整整型数是不可可修改的,同同时指针也是是不可修改的的)。如果应应试者能正确确回答这些问问题,那么他他就给我留下下了一个好印印象。顺带提提一句,也许许你可能会问问,即使不用用关键字coonst,也也还是能很容容易写出功能能正确的程序序,那么我为为什么还要如如此看重关键键字consst呢?我也也如下的几下下理由: 1). 关键字字constt的作用是为为给读你代码码的人传达非非常有用的信信
14、息,实际上上,声明一个个参数为常量量是为了告诉诉了用户这个个参数的应用用目的。如果果你曾花很多多时间清理其其它人留下的的垃圾,你就就会很快学会会感谢这点多多余的信息。(当当然,懂得用用constt的程序员很很少会留下的的垃圾让别人人来清理的。) 2). 通过给给优化器一些些附加的信息息,使用关键键字consst也许能产产生更紧凑的的代码。 3). 合理地地使用关键字字constt可以使编译译器很自然地地保护那些不不希望被改变变的参数,防防止其被无意意的代码修改改。简而言之之,这样可以以减少bugg的出现。Volatille 8. 关键字vvolatiile有什么么含意 并给出三个个不同的例子子
15、。一个定义为voolatille的变量是是说这变量可可能会被意想想不到地改变变,这样,编编译器就不会会去假设这个个变量的值了了。精确地说说就是,优化化器在用到这这个变量时必必须每次都小小心地重新读读取这个变量量的值,而不不是使用保存存在寄存器里里的备份。下下面是vollatilee变量的几个个例子: 1). 并行设设备的硬件寄寄存器(如:状态寄存器器) 2). 一个中中断服务子程程序中会访问问到的非自动动变量(Noon-auttomatiic varriablees) 3). 多线程程应用中被几几个任务共享享的变量 回答不出这个问问题的人是不不会被雇佣的的。我认为这这是区分C程序员和嵌嵌入式系
16、统程程序员的最基基本的问题。嵌嵌入式系统程程序员经常同同硬件、中断断、RTOSS等等打交道道,所用这些些都要求voolatille变量。不不懂得vollatilee内容将会带带来灾难。 假设被面试者正正确地回答了了这是问题(嗯嗯,怀疑这否否会是这样),我我将稍微深究究一下,看一一下这家伙是是不是直正懂懂得volaatile完完全的重要性性。 1). 一个参参数既可以是是constt还可以是voolatille吗?解释释为什么。 2). 一个指指针可以是vvolatiile 吗?解释为什么么。 3). 下面的的函数有什么么错误: int squuare(vvolatiile innt *pttr
17、) return *ptr * *pttr; 下面是答案: 1). 是的。一一个例子是只只读的状态寄寄存器。它是是volattile因为为它可能被意意想不到地改改变。它是cconst因因为程序不应应该试图去修修改它。 2). 是的。尽尽管这并不很很常见。一个个例子是当一一个中服务子子程序修该一一个指向一个个buffeer的指针时时。 3). 这段代代码的有个恶恶作剧。这段段代码的目的的是用来返指指针*ptrr指向值的平平方,但是,由由于*ptrr指向一个voolatille型参数,编编译器将产生生类似下面的的代码: int squuare(vvolatiile innt *pttr) int
18、a,bb; a = *pttr; b = *pttr; return a * bb; 由于*ptr的的值可能被意意想不到地该该变,因此aa和b可能是不同同的。结果,这这段代码可能能返不是你所所期望的平方方值!正确的的代码如下: long sqquare(volattile iint *pptr) int a; a = *pttr; return a * aa; 位操作(Bitt maniipulattion)9. 嵌入式系系统总是要用用户对变量或或寄存器进行行位操作。给给定一个整型型变量a,写两段代代码,第一个个设置a的bit 33,第二个清清除a 的bit 33。在以上两两个操作中,要要保持
19、其它位位不变。对这个问题有三三种基本的反反应 1). 不知道道如何下手。该该被面者从没没做过任何嵌嵌入式系统的的工作。 2). 用biit fieelds。Bit ffieldss是被扔到C语言死角的的东西,它保保证你的代码码在不同编译译器之间是不不可移植的,同同时也保证了了的你的代码码是不可重用用的。我最近近不幸看到IInfineeon为其较较复杂的通信信芯片写的驱驱动程序,它它用到了biit fieelds因此此完全对我无无用,因为我我的编译器用用其它的方式式来实现biit fieelds的。从从道德讲:永永远不要让一一个非嵌入式式的家伙粘实实际硬件的边边。 3). 用 #definnes
20、 和 bit maskss 操作。这这是一个有极极高可移植性性的方法,是是应该被用到到的方法。最最佳的解决方方案如下: #definee BIT33 (0 x11 6) puuts( 6) : putts(6。原原因是当表达达式中存在有有符号类型和和无符号类型型时所有的操操作数都自动动转换为无符符号类型。 因此-20变成了了一个非常大大的正整数,所所以该表达式式计算出的结结果大于6。这一点对对于应当频繁繁用到无符号号数据类型的的嵌入式系统统来说是丰常常重要的。如如果你答错了了这个问题,你你也就到了得得不到这份工工作的边缘。13. 评价下下面的代码片片断:unsigneed intt zeroo
21、 = 0; unsigneed intt comppzero = 0 xFFFFF; /*1s ccompleement of zeero */对于一个intt型不是16位的处理理器为说,上上面的代码是是不正确的。应应编写如下:unsigneed intt comppzero = 0;这一问题真正能能揭露出应试试者是否懂得得处理器字长长的重要性。在在我的经验里里,好的嵌入入式程序员非非常准确地明明白硬件的细细节和它的局局限,然而PPC机程序往往往把硬件作作为一个无法法避免的烦恼恼。 到了这个阶段,应应试者或者完完全垂头丧气气了或者信心心满满志在必必得。如果显显然应试者不不是很好,那那么这个测试
22、试就在这里结结束了。但如如果显然应试试者做得不错错,那么我就就扔出下面的的追加问题,这这些问题是比比较难的,我我想仅仅非常常优秀的应试试者能做得不不错。提出这这些问题,我我希望更多看看到应试者应应付问题的方方法,而不是是答案。不管管如何,你就就当是这个娱娱乐吧动态内存分配(Dynamic memory allocation)14. 尽管不不像非嵌入式式计算机那么么常见,嵌入入式系统还是是有从堆(hheap)中中动态分配内内存的过程的的。那么嵌入入式系统中,动动态分配内存存可能发生的的问题是什么么?这里,我期望应应试者能提到到内存碎片,碎碎片收集的问问题,变量的的持行时间等等等。这个主主题已经在
23、EESP杂志中中被广泛地讨讨论过了(主主要是 P.J. Pllaugerr, 他的解解释远远超过过我这里能提提到的任何解解释),所有有回过头看一一下这些杂志志吧!让应试试者进入一种种虚假的安全全感觉后,我我拿出这么一一个小节目:下面的代码码片段的输出出是什么,为为什么?char *pptr; if (pttr = (char *)mallloc(00) = NULLL) puts(GGot a null pointter); else puts(GGot a validd poinnter); 这是一个有趣的的问题。最近近在我的一个个同事不经意意把0值传给了函函数mallloc,得到到了一个合法法的指针之后后,我才想到到这个问题。这这就是上面的的代码
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论