void GetMemory2(char **p, int num) { *p = (char *)malloc(sizeof(char) * num); } void Test2(void) { char *pt = NULL; GetMemory2(&pt, 100); // 注意参数是 &pt,而不是pt strcpy(str, "hello"); cout<< str << endl; free(str); } |
由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,见示例:
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); } |
用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return语句用错了。这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡,见示例:
char *GetString(void) { char p[] = "hello china"; return p; // 编译器将提出警告 } void Test4(void) { char *str = NULL; str = GetString(); // str 的内容是垃圾 cout<< str << endl; } |
用调试器逐步跟踪Test4,发现执行str = GetString语句后str不再是NULL指针,但是str的内容不是“hello china”而是垃圾。
如果把上述示例改写成如下示例,会怎么样?
char *GetStringF(void) { char *p = "china"; return p; } void Test5(void) { char *str = NULL; str = GetStringF(); cout<< str << endl; } |
函数Test5运行虽然不会出错,但是函数GetStringF的设计概念却是错误的。因为GetStringF内的“china”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetStringF,它返回的始终是同一个“只读”的内存块。