12个有趣的C语言问答

0. gets() 方法

 

 

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

 

 

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

#include<stdio.h>
 
int main(void)
{
    char buff;
    memset(buff,0,sizeof(buff));
 
    gets(buff);
 
    printf("\n The buffer entered is \n",buff);
 
    return 0;
}

 

 

1 strcpy() 方法

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

#include<stdio.h>
 
int main(int argc, char *argv)
{
    int flag = 0;
    char passwd;
 
    memset(passwd,0,sizeof(passwd));
 
    strcpy(passwd, argv);
 
    if(0 == strcmp("LinuxGeek", passwd))
    {
        flag = 1;
    }
 
    if(flag)
    {
        printf("\n Password cracked \n");
    }
    else
    {
        printf("\n Incorrect passwd \n");
 
    }
    return 0;
}

 

 

2 main() 方法的返回类型

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

#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’ 返回类型能够让程序返回状态值。尤其是当这段程序作为其他应用的附属程序时这个状态值将更加重要。

 

 

3 ,内存泄露

 

 

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

#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

 

 

4 free() 方法

 

 

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

#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, 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() 方法中引起崩溃。

 

 

5 atexit with _exit

 

 

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

#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() 等。

 

 

6 void* C 结构体

 

 

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

 

 

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

int func(void *ptr)

 

 

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

 

 

7 * ++ 操作符

 

 

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

#include<stdio.h>
 
int main(void)
{
    char *ptr = "Linux";
    printf("\n  \n",*ptr++);
    printf("\n  \n",*ptr);
 
    return 0;
}

 

 

A: 以上的输出将是 :

 

 

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

 

 

8 Making changes in Code segment

 

 

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

#include<stdio.h>
 
int main(void)
{
    char *ptr = "Linux";
    *ptr = 'T';
 
    printf("\n  \n", ptr);
 
    return 0;
}

 

 

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

 

 

9 Process that changes its own name

 

 

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

 

 

A: 以下代码可以完成

#include<stdio.h>
 
int main(int argc, char *argv)
{
    int i = 0;
    char buff;
 
    memset(buff,0,sizeof(buff));
 
    strncpy(buff, argv, sizeof(buff));
    memset(argv,0,strlen(buff));
 
    strncpy(argv, "NewName", 7);
 
    // Simulate a wait. Check the process
    // name at this point.
    for(;i<0xffffffff;i++);
 
    return 0;
}

 

 

A ,局部变量的返回地址

 

 

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

#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  \n", *val);
 
    return 0;
}

 

 

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

 

 

B ,处理 printf() 参数

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

#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: 输出将是

110..40..60

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

 

全部评论
看了问题0,3个问题,1c语言有string类型? 2memset不是在string.h中么? 3gets()函数应该是把一个char 指针作为参数的吧?
点赞 回复 分享
发布于 2015-07-18 20:54

相关推荐

07-03 11:02
中山大学 C++
字节刚oc,但距离九月秋招很近了有两段互联网实习,非腾讯字节。不敢赌转正,现在在纠结去还是不去如果实习俩月离职会有什么后果吗
阿城我会做到的:不去后悔一辈子,能否转正取决于ld的态度,只要他不卡,答辩就是走流程,个人觉得可以冲一把
投递字节跳动等公司9个岗位
点赞 评论 收藏
分享
06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
头顶尖尖的程序员:我是26届的不太懂,25届不应该是找的正式工作吗?为什么还在找实习?大四还实习的话是为了能转正的的岗位吗
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务