c语言面试题
1.gets()函数
问:请找出下面代码里的问题: 礼仪
#include<stdio.h> int main(void) { char buff[10]; memset(buff,0,sizeof(buff)); gets(buff); printf("\n The buffer entered is [%s]\n",buff); return 0; }答:上面代码里的问题在于函数gets()的使用,这个函数从stdin接收一个字符串而不检查它所复制的缓存的容积,这可能会导致缓存溢出。这里推荐使用标准函数fgets()代替。 面试问题
2.strcpy()函数 面试问题
问:下面是一个简单的密码保护功能,你能在不知道密码的情况下将其破解吗? 面试网
文帝问殷景仁曰:“谁可继道济 ?”答曰:“道济以累有战功,故致威名,余但未任耳。”帝曰:“不然,昔李广在朝,匈奴不敢南望,后继者复有几人?”二十七年,魏军至瓜步,文帝登石头城望,甚有忧色。叹曰:“若道济在,岂至此!”
答:破解上述加密的关键在于利用攻破strcpy()函数的漏洞。所以用户在向“passwd”缓存输入随机密码的时候并没有提前检查 “passwd”的容量是否足够。所以,如果用户输入一个足够造成缓存溢出并且重写“flag”变量默认值所存在位置的内存的长“密码”,即使这个密码无法通过验证,flag验证位也变成了非零, 也就可以获得被保护的数据了。例如: 求职面试
$ ./psswd aaaaaaaaaaaaa Password cracked虽然上面的密码并不正确,但我们仍然可以通过缓存溢出绕开密码安全保护。 面试网
要避免这样的问题,建议使用 strncpy()函数。 求职信息
当时宋朝的国事已经无法挽回,金履祥于是决定放弃通过科举做官的愿望。但自负有治理国家拯救万民的才略,也不忍心立刻舍弃救世之心。正逢襄樊的宋军日益告急,宋朝官兵坐视危亡而不敢救援,金履祥因此奏言牵制敌军攻其虚弱的计策,请求派大军由海路直奔燕、蓟,那么围困襄樊的大军,就可以不攻自退了。而且详尽地叙述了海船经过的路线,所有的州郡县邑,以及大洋海岛,途中的困难与便利,以及各处里程的远近,清清楚楚,可依据实行。宋朝最终也未能采用。等到后来朱瑄、张清向元朝进言海运的便利,而所经过的海道,与履祥当年的上书相对照,没有丝毫差异,于是人们才佩服履祥学问的精确。 面试网
作者注:最近的编译器会在内部检测栈溢出的可能,所以这样往栈里存储变量很难出现栈溢出。在我的gcc里默认就是这样,所以我不得不使用编译命令‘-fno-stack-protector’来实现上述方案。
qzm4
3.main()的返回类型
礼仪
问:下面的代码能 编译通过吗?如果能,它有什么潜在的问题吗? 求职面试
#include<stdio.h> void main(void) { char *ptr = (char*)malloc(10); if(NULL == ptr) { printf("\n Malloc failed \n"); return; } else { // Do some processing free(ptr); } return; }答:因为main()的返回类型,这段代码的错误在大多数编译器里会被当作警告。main()的返回类型应该是“int”而不是“void”。因为“int”返回类型会让程序返回状态值。这点非常重要,特别当程序是作为依赖于程序成功运行的脚本的一部分运行时。 求职信息
D. 而是时青宫旧奄刘瑾等八人号“八虎” /日导帝狗马/鹰兔/歌舞/角抵/不亲万几/文每退朝/对僚属/语及辄泣下/
求职面试
4.内存泄露
求职面试
问:下面的代码会导致内存泄漏吗? 礼仪
#include<stdio.h> void main(void) { char *ptr = (char*)malloc(10); if(NULL == ptr) { printf("\n Malloc failed \n"); return; } else { // Do some processing } return; }答:尽管上面的代码并没有释放分配给“ptr”的内存,但并不会在程序退出后导致内存泄漏。在程序结束后,所有这个程序分配的内存都会自动被处理掉。但如果上面的代码处于一个“while循环”中,那将会导致严重的内存泄漏问题!
提示:如果你想知道更多关于内存泄漏的知识和内存泄漏检测工具,可以来看看我们在Valgrind上的。 求职信息
5.free()函数 礼仪
问:下面的程序会在用户输入'freeze'的时候出问题,而'zebra'则不会,为什么?
答:这里的问题在于,代码会(通过增加“ptr”)修改while循环里“ptr”存储的地址。当输入“zebra”时,while循环会在执行前被终止,因此传给free()的变量就是传给malloc()的地址。但在“freeze”时,“ptr”存储的地址会在while循环里被修改,因此导致传给free()的地址出错,也就导致了seg-fault或者崩溃。
qzm4
6.使用_exit退出
问:在下面的代码中,atexit()并没有被调用,为什么?
这是因为_exit()函数的使用,该函数并没有调用atexit()等函数清理。如果使用atexit()就应当使用exit()或者“return”与之相配合。 面试问题
参考pik_sock..c 文件(在机试主目录下),用socket编程在TCP/IP 协议下实现客户端与服务器间的通信,也可不用pik_sock.c 提供的非系统函数。(指定文件名为TcpServer.c 和 TcpClient.c) 礼仪
7. 写一个“标准”宏MIN,
这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) (A) : )) 求职面试
这个测试是为下面的目的而设的:
礼仪
1). 标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。 2). 三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。 3). 懂得在宏中小心地把参数用括号括起来 4). 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事? least = MIN(*p++, b); 面试问题
8. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢? qzm4
这个问题用几个解决方案。我首选的方案是: while(1) { } 一些程序员更喜欢如下方案: for(;;) { } 这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的 基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。 第三个方案是用 goto Loop: ... goto Loop; 应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。 面试网
9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。
面试网
对这个问题有三种基本的反应 1). 不知道如何下手。该被面者从没做过任何嵌入式系统的工作。 2). 用bit fields。Bit fields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到 Infineon为其较复杂的通信芯片写的驱动程序,它用到了bit fields因此完全对我无用,因为我的编译器用其它的方式来实现bit fields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。 3). 用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下: #define BIT3 (0x1<<3) static int a; void set_bit3(void) { a |= BIT3; } void clear_bit3(void) { a &= ~BIT3; } 一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。 面试网
qzm4
10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。 qzm4
这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着风格不同而不同。典型的类似代码如下: int *ptr; ptr = (int *)0x67a9; *ptr = 0xaa55; 求职信息
一个较晦涩的方法是: *(int * const)(0x67a9) = 0xaa55;
即使你的品味更接近第二种方案,但我建议你在时使用第一种方案。 求职信息
声明:c语言面试题来源于互联网,其版权均归原作者及其网站所有,本站虽力求保存原有的版权信息,但由于诸多原因,可能导致无法确定其真实来源,如果您对本站文章、图片资源的归属存有异议,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意!