C指针作为参数的程序分析我在看林锐博士的《高质量程序设计指南》这本书的时候,书最后面有一份习题,上面有一
C指针作为参数的程序分析
我在看林锐博士的《高质量程序设计指南》这本书的时候,书最后面有一份习题,上面有一个这样的题目:
有如下两个程序:
[程序1:]
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}
int main()
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello world!");
printf(str);
printf("\n");
system("pause");
return 0;
}
程序1可以正常的输出“hello world”
但是会“内存泄露”
但是请看程序2
[程序2:]
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
int main()
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world!");
printf(str);
printf("\n");
system("pause");
return 0;
}
程序2运行时程序会崩溃
问:有点不明白用malloc动态分配内存,两个程序中GetMemory函数内部分别是怎么实现的?还请各位解释清楚一点,我现在是似懂非懂的感觉,懂一点,但是不能深层次的解释问题。
[解决办法]程序1 malloc没有free
程序2 str没有分配内存
[解决办法]第二个实际上只是为形参分配了内存,实参并未分配到内存,因为在进入函数GetMemory时,形参指针 p 会成为实参指针 str 的一份复制(值拷贝),所以函数 GetMemory 执行后,形参 p 指向了分配到的内存,而实参 p 的值没有改变,自然在后面向 str 指向的内存拷贝字符串的时候必崩溃无疑。
详细的描述可以参考 http://blog.csdn.net/zhcosin/article/details/8275603
[解决办法]有点不明白用malloc动态分配内存,两个程序中GetMemory函数内部分别是怎么实现的?
明白兩點
1.指針的概念,
2.c語言函數参數的傳遞,
void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
1. p都是GetMemory的局部變量,函數運行結束,p是不存在的。
2. char **p. 這個p表示一個指針的地址,有這個地址,你就可以向這個地址的内存空間放數據。
3. GetMemory(&str, 100);取得變量str的地址,傳給p
*p = (char *)malloc(num); 將分配好的空間的地址,放到地址p所指的内存空間処,其實就是str所佔的内存空間, 這樣str的就改變了。
4. 明白了上面的,GetMemory(str);就很容易理解了。
[解决办法]传参传的是拷贝,这点弄明白就可以举一反三了。第二个情况内存是在拷贝的地址上分配的,str = NULL并未改变。
[解决办法]函数参数的传递方式:地址传递和值传递。
程序1是地址传递,也就是传进来一个地址,此时的形参是实参的一个拷贝,但这并没有影响到修改该地址所指向的内存中的内容,所以程序1可以输出结果,但是程序没有free,所以会存在内存泄露
程序2是值传递,传进来一个实参的副本,也就是拷贝了一个地址,此时在函数体重对这个地址重新赋值了,但是并没有影响到实参的变换,所以此时实参地址指向的内存中的内容还是空的。
[解决办法]实际上这是参数传递的问题,看起来是传地址,其本质是传值。
str的值(NULL)传给了p,p只是str的一个复印件,复印件的内容发生了改变(指向了新的地址),
但原件str的值是不会发生改变的(还是NULL).
所以你的strcpy(str, "hello world!");是错误的!
[解决办法]第一个由于没有手动释放内存自然会有内存泄露
第二个就是传参的话,也是传递过去一个智者你的副本,申请的空间只是给这个副本,并且这个自定义函数没有返回值的,要是申请完毕了然后返回该指针还是可以的
这样就行了
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *GetMemory(char *p)
{
p = (char *)malloc(100);
return p;
}
int main()
{
char *str = NULL;
str=GetMemory(str);
strcpy(str, "hello world!");
printf(str);
printf("\n");
system("pause");
return 0;
}
[解决办法]对了
忘了释放内存
应该是这样
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *GetMemory(char *p)
{
p = (char *)malloc(100);
return p;
}
int main()
{
char *str = NULL;
str=GetMemory(str);
strcpy(str, "hello world!");
printf(str);
printf("\n");
free(str);
system("pause");
return 0;
}