12个关于C语言的有趣问答
本文汇总了12个关于C语言的问答,对于加深对C语言程序设计的难点理解很有帮助,读者可参考一下:
1、gets()方法
问:以下代码有个被隐藏住的问题,你能找到它吗?
答:这个不显眼的问题就是使用了gets()方法。此方法接受一个string类型参数,但是却没有检测此数值是否有足够的空间来拷贝数据。所以这里我们一般用fgets()方法将来的更好。
#include<stdio.h> intmain(void) { charbuff[10]; memset(buff,0,sizeof(buff)); gets(buff); printf("\nThebufferenteredis[%s]\n",buff); return0; }
2、strcpy()方法
问:密码防护是很基本的功能,看看能否搞定下面这段代码?
#include<stdio.h> intmain(intargc,char*argv[]) { intflag=0; charpasswd[10]; memset(passwd,0,sizeof(passwd)); strcpy(passwd,argv[1]); if(0==strcmp("LinuxGeek",passwd)) { flag=1; } if(flag) { printf("\nPasswordcracked\n"); } else { printf("\nIncorrectpasswd\n"); } return0; }
3、main()方法的返回类型
问:请问下面这段代码能否通过编译?如果能的话,那么这段代码中隐含什么问题吗?
#include<stdio.h> voidmain(void) { char*ptr=(char*)malloc(10); if(NULL==ptr) { printf("\nMallocfailed\n"); return; } else { //Dosomeprocessing free(ptr); } return; }
答:答案是代码能通过编译,但是会留下针对main()方法的返回类型的警告。main()方法的真正返回类型应该为'int'而非'void'。这是因为'int'返回类型能够让程序返回状态值。尤其是当这段程序作为其他应用的附属程序时这个状态值将更加重要。
4、内存泄露
问:请问以下代码有内存泄露吗?
#include<stdio.h> voidmain(void) { char*ptr=(char*)malloc(10); if(NULL==ptr) { printf("\nMallocfailed\n"); return; } else { //Dosomeprocessing } return; }
答:好,虽然上面的代码没有对指针ptr进行内存释放,但实际上即使是程序结束也不会造成内存泄露,因为当程序结束时所有一开始被占据的内存就全部清空了。但如果上面这段代码是在while循环里面那将会造成严重的问题
补充:如果你需要了解更多关于内存泄露的问题,你可以参考这篇文章https://www.nhooo.com/article/41216.htm
5、free()方法
问:以下代码当用户输入'freeze'时会奔溃,而如果输入'zebra'则运行正常,这是为什么?
#include<stdio.h> intmain(intargc,char*argv[]) { char*ptr=(char*)malloc(10); if(NULL==ptr) { printf("\nMallocfailed\n"); return-1; } elseif(argc==1) { printf("\nUsage\n"); } else { memset(ptr,0,10); strncpy(ptr,argv[1],9); while(*ptr!='z') { if(*ptr=='') break; else ptr++; } if(*ptr=='z') { printf("\nStringcontains'z'\n"); //Dosomemoreprocessing } free(ptr); } return0; }
答:问题的根源是因为代码在while循环中改变了ptr指针的地址。当输入为'zebra'时,while循环甚至在执行第一遍前就结束了,所以free()释放的内存地址就是一开始malloc()分配的地址。但是当输入'freeze'时,ptr记录的地址在while循环中被更改,因为将会是错误的地址传递到free()方法中引起崩溃。
6、atexitwith_exit
问:在以下代码,atexit()方法并没有被调用,你知道为什么吗?
#include<stdio.h> voidfunc(void) { printf("\nCleanupfunctioncalled\n"); return; } intmain(void) { inti=0; atexit(func); for(;i<0xffffff;i++); _exit(0); }
答:这是因为使用了_exit()方法。此方法并没有调用清除数据相关的方法,比如atexit()等。
7、void*与C结构体
问:能否设计一个方法接受任意类型的参数然后返回整数?同时是否有办法传递多个这样的参数?
A:一个能接受任意类型参数的方法像下面这个样子:
intfunc(void*ptr)
如果需要传递多个参数,那么我们可以传递一个包含这些参数的结构体
8、*与++操作符
问:以下代码将输出什么?为什么?
#include<stdio.h> intmain(void) { char*ptr="Linux"; printf("\n[%c]\n",*ptr++); printf("\n[%c]\n",*ptr); return0; }
答:以上的输出将是:
因为++与*的优先级一样,所以*ptr++将会从右向左操作。按照这个逻辑,ptr++会先执行然后执行*ptr。所以第一个结果是'L'。也因为++被执行了,所以下一个printf()结果是'i'。
9、MakingchangesinCodesegment
问:以下代码运行时一定会崩溃,你能说出原因吗?
#include<stdio.h> intmain(void) { char*ptr="Linux"; *ptr='T'; printf("\n[%s]\n",ptr); return0; }
答:这是因为,通过*ptr=‘T',此行代码尝试更改只读内存存储的字符串'Linux'。此操作当然行不通所以才会造成崩溃。
10、Processthatchangesitsownname
问:你能否写一个程序在它运行时修改它的名称?
答:以下代码可以完成
#include<stdio.h> intmain(intargc,char*argv[]) { inti=0; charbuff[100]; memset(buff,0,sizeof(buff)); strncpy(buff,argv[0],sizeof(buff)); memset(argv[0],0,strlen(buff)); strncpy(argv[0],"NewName",7); //Simulateawait.Checktheprocess //nameatthispoint. for(;i<0xffffffff;i++); return0; }
11、局部变量的返回地址
问:下面的代码有问题吗?如果有,如何修改?
#include<stdio.h> int*inc(intval) { inta=val; a++; return&a; } intmain(void) { inta=10; int*val=inc(a); printf("\nIncrementedvalueisequalto[%d]\n",*val); return0; }
答:虽然上面的代码有时运行会很好,但是在方法inc()中有很严重的隐患。当inc()方法执行后,再次使用局部变量的地址就会造成不可估量的结果。解决之道就是传递变量a的地址给main()。
12、处理printf()参数
问:以下代码输出请问是什么?
#include<stdio.h> intmain(void) { inta=10,b=20,c=30; printf("\n%d..%d..%d\n",a+b+c,(b=b*2),(c=c*2)); return0; }
答:输出将是
110..40..60
这是因为参数都是从右向左处理的,然后打印出来却是从左向右。