指向指针的指针申请动态内存

在《高质量c编程指南》中,提到了 如果函数的参数是一个指针,那么别指望它能申请动态内存
代码如下:

#include
#include
void GetMemory(char *p,int num);

int main()
{
    char* stu=NULL;
    GetMemory(stu,100);
    printf("%d\n",stu);
    return 0;
}

void GetMemory(char *p,int num)
{
    p=(char *)malloc(num);//企图申请动态内存
}

最后的输出的stu的结果是0,即NULL。说明p没有为stu成功申请到动态内存,stu仍然是初始化时候的NULL.
正如《高质量c编程指南》书里说的,问题出在了GetMemory()会为参数制作临时的副本。即,为指针p制作了一个副本_p,其中_p=p=address,所以_p和p都是指向同一变量的。如下图所示:
指向指针的指针申请动态内存_第1张图片
而现在真正执行的是 _p=(char *)malloc(num);所以申请动态内存后首地址address1返回给了指针_p,所以说现在_p指向了动态内存段了,而p一点改变都没有,所以stu仍然是NULL。
指向指针的指针申请动态内存_第2张图片

所以GetMemory函数事实上没有为stu申请到动态内存,相反的,_p作为临时变量在该函数执行后就被销毁了,而动态内存却因为没有free()释放,出现内存泄露。每调用一次GetMemory函数,就出现一次内存泄露。所以不要使用作为函数参数的指针申请动态内存。

可以用的方法可以是用指向指针的指针申请动态内存。
具体代码如下:

#include
#include
void GetMemory(char **p,int num);//参数p是二重指针,指向指针的指针

int main()
{
    char* stu=NULL;
    GetMemory(&stu,100);//注意这里是&stu
    printf("%d\n",stu);
    return 0;
}

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

该怎么理解这个问题呢。首先我们来看下什么是指向指针的指针。
指向指针的指针申请动态内存_第3张图片
现在定义了char **p;
所以p是二重的指针,类型为char **,
所以正如一般的指针变量都是放着要访问的变量的地址,现在,指针变量p里面放着的正是*p的地址Addr_2,
(*p)的类型是char *,所以它的内容也是放着一个地址,
就是**p的地址Addr_3。而地址Addr_3里面放着的就是一个char型的变量的值。正如上图所示的。
好了,现在看一下,参数&stu是怎么传递的,如下图
指向指针的指针申请动态内存_第4张图片
现在我们参数的传递是&stu=p;那么按照上面的说法,GetMemory函数为p配置的临时变量_p=p=&stu;那么*_p也就是stu
所以真正执行的语句*_p=(char *)malloc(num);
也就是执行的stu=(char *)malloc(num);所以说stu已经得到了动态内存的首地址了。如下图。
指向指针的指针申请动态内存_第5张图片
所以,这次申请动态内存是有效的。
这就是指向指针的指针的方式来在子函数里面申请动态内存。
不知道你们理解了没有,如果觉得有错误,欢迎指正,共同学习。谢谢。

你可能感兴趣的:(C/C++)