科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件水滴石穿C语言之编译器引出的问题

水滴石穿C语言之编译器引出的问题

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本节主要探讨C编译器下面两方面的特点所引发的一系列常见的编程问题。

作者:楚云风 来源:天极网 2007年10月28日

关键字: Linux

  • 评论
  • 分享微博
  • 分享邮件
问题:编译器会给函数的参数隐含制造临时副本

  请问运行下面的Test函数会有什么样的结果?

void GetMemory2(char **p, int num)
{
 *p = (char *)malloc(num);
}

void Test(void)
{
 char *str = NULL;
 GetMemory(&str, 100);
 strcpy(str, "hello");
 printf(str);
}

  答案与分析:

  这是林锐的《C/C++高质量编程指南》上面的例子,拿来用一下。

  这样调用会产生如下两个后果:

  1)、能够输出hello

  2)、内存泄漏

   另一个相关问题:

  请问运行Test函数会有什么样的结果?

void GetMemory(char *p)
{
 p = (char *)malloc(100);
}

void Test(void)
{
 char *str = NULL;
 GetMemory(str);
 strcpy(str, "hello world");
 printf(str);
}

  答案与分析:

  后果严重,运行的结果是程序崩溃,通过运行调试我们可以看到,经过GetMemory后,Test函数中的 str仍旧是NULL。可想而知,一调用

strcpy(str, "hello world");

  程序必然崩溃了事。

  原因分析:

   C编译器总是会为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西,如果想要输出动态内存,请使用指向指针的指针,或者,使用指向引用的指针。

  问题:头文件和包含它的.c文件一同编译问

  下面的代码非常短小,看起来毫无问题,但编译器会报告一个错误,请问问题可能出现在什么地方?

#include "someheader.h"
int myint = 0;

  答案与分析:

  不用盯着int myint = 0;看,这一句赋值应该是C语言中最简单的语句,问题肯定不会出在它身上,那么问题只可能出现在someheader.h中,最常见的就是该头文件的最后一行的声明(函数也好,变量也好)没有用分号";"结尾,那么编译器会将它和myint变量结合起来考虑,自然就会出错了。

  这个问题主要是提醒你,在定位问题时思路要拓宽一点,可能要考虑一下所包含的头文件是否有问题。

  结论:被包含的头文件是和.c文件一起编译的,头文件中的问题会反映到.c文件编译中去的,切记。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章