7.4指针参数是如何传递内存的?

在看林锐的书。
7.4指针参数是如何传递内存的?
----------------------下边的例子是我确定犯过的错误,并且之后不能保证就记得住不犯
特意记下来。
 

7.4指针参数是如何传递内存的?

若是函数的参数是一个指针,不要期望用该指针去申请动态内存。示例 7-4-1 中, Test 数的语句 GetMemory(str, 200) 并无使 str 得到指望的内存, str 依旧是 NULL ,为何?
v oid 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"); // 运行错误
}
示例 7-4-1  试图用指针参数申请动态内存
毛病出在函数 GetMemory 中。编译器老是要为函数的每一个参数制做临时副本,指针参数 p 的副本是  _p ,编译器使  _p = p 。若是函数体内的程序修改了 _p 的内容,就致使参数 p 的内容做相应的修改。这就是指针能够用做输出参数的缘由。在本例中, _p 申请了新的内存,只是把 _p 所指的内存地址改变了,可是 p 丝毫未变。因此函数 GetMemory 并不能输出任何东西。事实上,每执行一次 GetMemory 就会泄露一块内存,由于没有用 free 释放内存。
若是非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见示例 7-4- 2
void GetMemory2(char **p, int num)
{
* p = (char *)malloc(sizeof(char) * num);
}
void Test2(void)
{
char *str = NULL;
GetMemory2(&str, 100); // 注意参数是  &str ,而不是 str
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
示例 7-4- 2用指向指针的指针申请动态内存
因为 “指向指针的指针”这个概念不容易理解,咱们能够用函数返回值来传递动态内存。这种方法更加简单,见示例 7-4- 3
char *GetMemory3(int num)
{
char *p = (char *)malloc(sizeof(char) * num);
return p;
}
void Test3(void)
{
char *str = NULL;
str = GetMemory3(100);
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
示例 7-4- 用函数返回值来传递动态内存
用函数返回值来传递动态内存这种方法虽然好用,可是经常有人把 return 语句用错了。这里强调不要用 return 语句返回指向“栈内存”的指针,由于该内存在函数结束时自动消亡,见示例 7-4- 4
char * GetString (void)
{
char p[] = "hello world";
return p; //  编译器将提出警告
}
void Test4(void)
{
char * str  =   NULL;
str  =  GetString (); //  str  的内容是垃圾
cout<<  str  << endl;
}
示例 7-4- return 语句返回指向“栈内存”的指针
用调试器逐步跟踪 Test4 ,发现执行 str = GetString 语句后 str 再也不是 NULL 指针,可是 str 的内容不是 hello world 而是垃圾。
若是把 示例 7-4- 4 改写成 示例 7-4- 5 ,会怎么样?
char *Get String 2(void)
{
char *p = "hello world";
return p;
}
void Test5(void)
{
char * str  = NULL;
str  =   Get String 2();
cout<<  str  << endl;
}
示例 7-4- return 语句返回常量字符串
函数 Test5 运行虽然不会出错,可是函数 GetString2 的设计概念倒是错误的。由于 GetString2 内的“ hello world ”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。不管何时调用 GetString2 ,它返回的始终是同一个“只读”的内存块。