序
一直以为自己的C语言学的不错,还自命不凡呢,2009-8-27,学习《数据结构》的链表的时候,才知道自己差的很远很远。C语言的学习,任重道远!!!终身受益!!!
问题的引出:关于链表的建立。先举出一个例子:
#include<stdio.h>
void GetMemory(char*p, int num)
{
p = (char*)malloc(sizeof(char)* num);
}
void Test(void)
{
char *str =NULL;
GetMemory(str, 100); // str 仍然为NULL
strcpy(str, "hello");// 运行错误
}
想不通,死活都想不明白。2009-8-27就想了一天了。为什么str仍然为NULL???
到底是为什么呀???
思考一天,未果!
问题解决
2009-8-28上网逛搜资料,大概明白一些,现解释如下:
林锐博士对以上问题的解释:
#include<stdio.h>
void GetMemory(char*p, int num)
{
p = (char*)malloc(sizeof(char)* num);
}
在本函数中,编译器总是要为函数的每个参数制作临时副本,参数p的副本就是_p, 编译器使得 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容做相应的修改,这就是指针可以用作输出参数的原因。在本例中_p申请了新的内存,只是把_p所指向的内存地址改变了,但是p却丝毫没有变化,所以函数GetMemory不能输出任何东西。更为令人感到担心的是:事实上,每执行一次GetMemory函数就会泄露一块内存,因为没有使用free()释放内存。
在《C和指针》一书中有如下的解释:C函数的所有参数均以“传值调用”方式进行传递,这意味着函数将会获得参数值的一份拷贝。这样,函数就可以放心的使用这个拷贝值,而不必担心会修改调用程序实际传递给它的参数。而“传址调用”和这个关系并无矛盾之处,传递给函数的就是这个指针的一份拷贝。有两个规则:
1. 传递给函数的标量参数是传值调用的。
2. 传递给函数的数组参数在行为上就像是它们是通过传址调用的那样。
#include<stdio.h>
void GetMemory(char**p, int num)
{
*p = (char*)malloc(sizeof(char)* num);
}
int main(void)
{
char *str =NULL;
GetMemory(&str, 100); // str 仍然为NULL
strcpy(str, "hello");// 运行错误
printf(str);
return 0;
}
试验结果,可行。分析: 使用了指针的指针。**p是指向str指针的指针的一个拷贝。在子函数中,修改*p的值,实际上是将这个拷贝值的指针指向了另外的地方(就是内存分配的地方),起到了修改的作用。
试验结论:
函数需要使用指针参数进行传入传出的,在函数中只能对指针的指向的值(*p)进行修改,而不能修改指针指向,也就是指针地址!(函数中不得修改指针参数的地址,否则请使用指针的指针!)
本文探讨了C语言中链表内存分配的常见误区,通过具体实例解析了为何直接在函数内为传入的指针分配内存无法改变原指针指向,并提供了正确的解决方案。
2063

被折叠的 条评论
为什么被折叠?



