问题:编译器会给函数的参数隐含制造临时副本
请问运行下面的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文件编译中去的,切记。
查看本文来源