转自:http://www.admin10000.com/document/913.html

1,gets() 方法

  Q:以下代码有个被隐藏住的问题,你能找到它吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
#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;
}

  A:这个不显眼的问题就是使用了 gets() 方法。此方法接受一个string类型参数,但是却没有检测此数值是否 有足够的空间来拷贝数据。所以这里我们一般用 fgets() 方法将来的更好。

2,strcpy() 方法

  Q:密码防护是很基本的功能,看看能否搞定下面这段代码?

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
   
int main(int argc, char *argv[])
{
    int flag = 0;
    char passwd[10];
   
    memset(passwd,0,sizeof(passwd));
   
    strcpy(passwd, argv[1]);
   
    if(0 == strcmp("LinuxGeek", passwd))
    {
        flag = 1;
    }
   
    if(flag)
    {
        printf("\n Password cracked \n");
    }
    else
    {
        printf("\n Incorrect passwd \n");
   
    }
    return 0;
}

3,main() 方法的返回类型

  Q:请问下面这段代码能否通过编译?如果能的话,那么这段代码中隐含什么问题吗?

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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;
}

  A:答案是代码能通过编译,但是会留下针对main()方法的返回类型的警告。main()方法的真正返回类型应该为'int'而非'void'。这是因为'int'返回类型能够让程序返回状态值。尤其是当这段程序作为其他应用的附属程序时这个状态值将更加重要。

4,内存泄露

  Q:请问以下代码有内存泄露吗?

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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;
}

  A:好,虽然上面的代码没有对指针 ptr 进行内存释放,但实际上即使是程序结束也不会造成内存泄露,因为当程序结束时所有一开始被占据的内存就全部清空了。但如果上面这段代码是在 while 循环里面那将会造成严重的问题。

  Note: 如果你需要了解更多关于内存泄露的问题以及如何使用工具检测内存泄露,你可以参考这篇文章 Valgrind

5,free() 方法

  Q:以下代码当用户输入'freeze'时会奔溃,而如果输入'zebra'则运行正常,这是为什么?

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<stdio.h>
   
int main(int argc, char *argv[])
{
    char *ptr = (char*)malloc(10);
   
    if(NULL == ptr)
    {
        printf("\n Malloc failed \n");
        return -1;
    }
    else if(argc == 1)
    {
        printf("\n Usage  \n");
    }
    else
    {
        memset(ptr, 0, 10);
   
        strncpy(ptr, argv[1], 9);
   
        while(*ptr != 'z')
        {
            if(*ptr == '')
                break;
            else
                ptr++;
        }
   
        if(*ptr == 'z')
        {
            printf("\n String contains 'z'\n");
            // Do some more processing
        }
   
       free(ptr);
    }
   
    return 0;
}

  A:问题的根源是因为代码在while循环中改变了 ptr 指针的地址。当输入为'zebra'时,while循环甚至在执行 第一遍前就结束了,所以free()释放的内存地址就是一开始malloc()分配的地址。但是当输入'freeze'时, ptr记录的地址在while循环中被更改,因为将会是错误的地址传递到free()方法中引起崩溃。

6,atexit with _exit

  Q:在以下代码,atexit()方法并没有被调用,你知道为什么吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
   
void func(void)
{
    printf("\n Cleanup function called \n");
    return;
}
   
int main(void)
{
    int i = 0;
   
    atexit(func);
   
    for(;i<0xffffff;i++);
   
    _exit(0);
}

  A:这是因为使用了 _exit() 方法。此方法并没有调用清除数据相关的方法,比如 atexit()等。

7,void* 与 C 结构体

  Q:能否设计一个方法接受任意类型的参数然后返回整数?同时是否有办法传递多个这样的参数?

  A:一个能接受任意类型参数的方法像下面这个样子:

 
1
int func(void *ptr)

  如果需要传递多个参数,那么我们可以传递一个包含这些参数的结构体

8,* 与 ++ 操作符

  Q:以下代码将输出什么?为什么?

 
1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
   
int main(void)
{
    char *ptr = "Linux";
    printf("\n [%c] \n",*ptr++);
    printf("\n [%c] \n",*ptr);
   
    return 0;
}

  A:以上的输出将是:

 
1
2
3
[L] 
   
[i]

  因为++与 * 的优先级一样,所以 *ptr++ 将会从右向左操作。按照这个逻辑,ptr++ 会先执行然后执行*ptr。所以第一个结果是'L'。也因为 ++ 被执行了,所以下一个printf() 结果是'i'。

9,Making changes in Code segment

  Q:以下代码运行时一定会崩溃,你能说出原因吗?

 
1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
   
int main(void)
{
    char *ptr = "Linux";
    *ptr = 'T';
   
    printf("\n [%s] \n", ptr);
   
    return 0;
}

  A:这是因为,通过 *ptr = 'T',此行代码尝试更改只读内存存储的字符串'Linux'。此操作当然行不通所以才会造成崩溃。

10,Process that changes its own name

  Q:你能否写一个程序在它运行时修改它的名称?

  A:以下代码可以完成

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
   
int main(int argc, char *argv[])
{
    int i = 0;
    char buff[100];
   
    memset(buff,0,sizeof(buff));
   
    strncpy(buff, argv[0], sizeof(buff));
    memset(argv[0],0,strlen(buff));
   
    strncpy(argv[0], "NewName", 7);
   
    // Simulate a wait. Check the process
    // name at this point.
    for(;i<0xffffffff;i++);
   
    return 0;
}

11,局部变量的返回地址

  Q:下面的代码有问题吗?如果有,如何修改?

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
   
int* inc(int val)
{
  int a = val;
  a++;
  return &a;
}
   
int main(void)
{
    int a = 10;
   
    int *val = inc(a);
   
    printf("\n Incremented value is equal to [%d] \n", *val);
   
    return 0;
}

  A:虽然上面的代码有时运行会很好,但是在方法 inc() 中有很严重的隐患。当inc()方法执行后,再次使用局部变量的地址就会造成不可估量的结果。解决之道就是传递变量a的地址给main()。

12,处理 printf() 参数

  Q:以下代码输出请问是什么?

 
1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
   
int main(void)
{
    int a = 10, b = 20, c = 30;
   
    printf("\n %d..%d..%d \n", a+b+c, (b = b*2), (c = c*2));
   
    return 0;
}

  A:输出将是

 
1
110..40..60

  这是因为参数都是从右向左处理的,然后打印出来却是从左向右。

英文原文:c-interview-questions

12个有趣的C语言问答的更多相关文章

  1. 12个有趣的C语言问答(详解)

    本文参照博文<12个有趣的C语言问答>,在原文的基础上增加来对应的知识点的详细介绍. 1 gets()方法 Q:下面的代码有一个被隐藏的问题,你能找到它吗? #include <st ...

  2. 《12个有趣的C语言问答》(4)

    C语言面试问答——<12个有趣的C语言问答>评析(4) 前文链接:http://www.cnblogs.com/pmer/p/3324063.html 8,Making changes i ...

  3. 《12个有趣的C语言问答》评析2

    <12个有趣的C语言问答>评析(2) 前文链接:http://www.cnblogs.com/pmer/p/3313913.html (没存盘,遭遇过热保护.至少4个问答的评论白写了.默哀 ...

  4. 12个滑稽的C语言面试问答——《12个有趣的C语言问答》评析(5)

    前文链接:http://www.cnblogs.com/pmer/archive/2013/09/17/3327262.html A,局部变量的返回地址 Q:下面的代码有问题吗?如果有,如何修改? # ...

  5. 12个有趣的c语言面试题&nbsp;

    1.gets()函数 问:请找出下面代码里的问题: #include int main(void) { char buff[10]; memset(buff,0,sizeof(buff)); gets ...

  6. 12个有趣的C语言面试题

    摘要:12个C语言面试题,涉及指针.进程.运算.结构体.函数.内存,看看你能做出几个! 1.gets()函数 问:请找出下面代码里的问题: #include<stdio.h> int ma ...

  7. Ubuntu 12.04上安装R语言

    Ubuntu 12.04上安装R语言 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ R的安装 sudo gedit /etc/apt/sources. ...

  8. 12个有趣的c面试题目

    1.gets()函数 问:请找出以下代码里的问题: #include<stdio.h>  int main(void)  {      char buff[10];      memset ...

  9. 一个有趣的C语言问题

    这个问题是知乎上的一个问题,看了以后觉得比较有意思.代码短到只有十多行,但是这么短的代码却输出了很奇怪的结果.很多人回答的时候都是站在理论的角度上说明代码的问题,但是实际的问题还是没有说明其中的问题. ...

随机推荐

  1. centos7-cockpit

    yum install cockpit* -y systemctl start cockpit.service systemctl enable cockpit.service 修改默认端口9090 ...

  2. 201971010110-李华《面向对象程序设计(java)》第七周学习总结

    博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...

  3. JAVA并发-Executor

    结构 类继承图: 上面的各个接口/类的关系和作用: Executor 执行器接口,也是最顶层的抽象核心接口, 分离了任务和任务的执行. ExecutorService 在Executor的基础上提供了 ...

  4. idea 配置 scala

    在setting 中,通过plugin 安装 Scala 然后重启idea 重启后,建一个scala文件,根据上面提示安装scala

  5. ASP.NET CoreMVC 中的视图

    ASP.NET Core MVC 中的视图 MVC 中的视图 用于显示Controller提供给它的 Model 的业务数据. 视图是带有嵌入 Razor 标记的 HTML 模板. 如果编程语言是 C ...

  6. 详解 ASP.NET Core MVC 的设计模式

    MVC 是什么?它是如何工作的?我们来解剖它 在本节课中我们要讨论的内容: 什么是 MVC? 它是如何工作的? 什么是 MVC MVC 由三个基本部分组成 - 模型(Model),视图(View)和控 ...

  7. Oracle RAC 修改SPFILE路径 文件查看

    在spfile场景下创建pfile: SQL> create pfile='/opt/oracle/init_pfile.ora'; 创建新spfile: SQL> create spfi ...

  8. 推荐一款移动端小视频App玲珑视频

    推荐一款移动端小视频App玲珑视频 一 应用描述 玲珑小视频,边看边聊![海量视频,刷个不停,还能找妹子语音聊天哦][随手拍一拍,记录美好生活,还能拿金币哦][看视频领金币.登录领金币.拍视频领金币. ...

  9. HTML连载28-标签的权重

    一.什么是优先级的权重 1.作用:当多个选择器混合在一起的时候,我们可以通过计算权重来判断谁的优先级最高. 2.权重的计算规则 公共代码: <body> <div id=" ...

  10. 关于wepy小程序图片显示问题

    如果图片资源在本地,用background-image 是无法找到本地资源的,只能通过image标签用src进行引入: 图片资源在服务器上,用背景图片和image进行引入,在安卓真机上测试是没有问题的 ...