12个有趣的C语言问答(详解)
1 gets()方法
Q:下面的代码有一个被隐藏的问题,你能找到它吗?
1 #include <stdio.h>
 2 
 3 int main(void)
 4 {
 5     char buff[10];
 6     memset(buff, 0, sizeof(buff));
 7     gets(buff);
 8     printf("%s\n", buff);
 9 
10     return 0;
11 }
A:这个不显眼的问题就是使用了gets()方法,其函数原型如下:
char* gets(char *s);
此方法接受一个字符数组参数,但是却没有检查此数组是否有足够的空间来拷贝数据。gets()函数是不安全的,不推荐使用,一般情况下编译器也会给出警告提示:the `gets' function is dangerous and should not be used。gets()不检查预留存储区是否能够容纳实际输入的数据。多出来的字符简单的溢出到相邻的存储区,可能会导致错误。
所以,这里我们一般用fgets()方法更好,函数原型如下:
char* fgets(char *s, int n, FILE *stream);
一般使用fgets()函数,都是读取文件当中的n-1个字符到s中,其实,此函数还有一个很好的用处就是从标准输入流中读取字符串,而且不用担心输入的字符个数超出了字符数组的大小而导致溢出的问题!要怎样做呢?如下:
char str[10];  
fgets(str, siezof(str), stdin);
值得注意的是:谨记fgets()只读取n-1个字符。所以,fgets()读取到换行符、文件尾或读完n-1个字符便会进行返回。
2 strcpy()方法
Q:密码防护是很基本的功能,看看能够搞定下面这一段代码?
1 #include <stdio.h>
 2 #include <memory.h>
 3 int main(int argc, char *argv[])
 4 {
 5     int flag = 0;
 6     char passwd[10];
 7 
 8     memset(passwd, 0, sizeof(passwd));
 9     strcpy(passwd, argv[1]);
10 
11     if (0 == strcmp("LinuxGeek", passwd)){
12         flag = 1;
13     }
14     if (flag){
15         printf("\n Password cracked \n");
16     }else{
17         printf("\n Incorrect password \n");
18     }
19 
20     return 0;
21 }
说明:该程序通过在运行时携带一个密码参数,然后程序会将用户输入的密码参数值与真实的密码比较,如果两者相等就输出cracked信息,否则输出incorrect提示。
3 main()函数的返回类型
Q:请问下面这段代码能否通过编译?如果能的话,那么这段代码中隐含什么问题吗?
#include <stdio.h>
#include <stdlib.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;
}
A:代码能通过编译,但是会留下针对main()函数返回值类型的警告。main()函数的真正返回值类型应该是int而不是void,这是因为int返回类型可以返回程序运行的状态值,尤其是当这段程序作为其他应用的附属程序时这个状态值将更加重要。
mainret.c:3:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
 void main(void)
      ^
4 内存泄漏
Q:请问,以下代码有内存泄漏吗?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    char *ptr = (char*)malloc(10);
    if (NULL == ptr){
        printf("\n Malloc failed \n");
        return -1;
    }else{
        //Do some processing
    }
return 0;
}
A:不会,虽然上面的代码没有对指针ptr进行内存释放,但实际上即使是程序结束也不会造成内存泄漏,因为当程序结束时所有一开始被占据的内存就全部清空了。但是,如果上面分配内存这段代码是在while循环里面那将会造成严重的问题。
5 free()方法
Q:以下代码,当用户输入'freeze'时会崩溃,而如果输入'zebra'则运行正常,为什么?
1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <memory.h>
 4 int main(int argc, char *argv[])
 5 {
 6     char *ptr = (char *)malloc(10);
 7 
 8     if (NULL == ptr){
 9         return -1;
10     }
11     if (argc == 1){
12         printf("\n Usage: add a string \n");
13     }else {
14         memset(ptr, 0, 10);
15         strncpy(ptr, argv[1], 9);
16         while (*ptr != 'z'){
17             if (*ptr == ' ') break;
18             else ptr++;
19         }
20         if (*ptr == 'z'){
21             printf("\n String contains 'z' \n");
22             //Do some more processing
23         }
24         free(ptr);
25     }
26 
27     return 0;
28 }

