用法1:
用作函数的返回值,比较常见的是返回分配的堆内存地址。
下面用一个例子进行说明下:
-
-
-
-
-
-
-
-
- bool get_memory(char *pst, unsigned int size)
- {
- if (0 == size)
- {
- pst = NULL;
- return false;
- }
-
- pst = (char*)malloc(size);
- if (NULL == pst)
- {
- return false;
- }
- memset(pst, 0, size);
-
- return true;
- }
-
- int use_get_memory()
- {
- char *pStr = NULL;
- char buf[] = "hello world.";
- get_memory(pStr, 1024);
-
- memcpy(pStr, buf, sizeof(buf));
-
- return 0;
- }
当我们运行这段程序的时候,会发现程序崩溃了,出错的原因是对内存的非法访问,为什么会出现这种情况呢,我们明明已经分配了内存的啊,那我们就进行调试一下,看看问题究竟出现在哪里,vs的调试截图如下:
![](https://img-blog.csdn.net/20151030090559970?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
发现调用get_memory函数之后,pStr所指向的内存竟然是空的,可见问题就出现在这里。
函数参数的传递是按值传递的,指针类型的参数其实也是按值进行传递的,只不过传递的是变量的地址,按值传递会进行拷贝,下面用一个图进行解释。
![](https://img-blog.csdn.net/20151030092032867?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
调用get_memory后,pStr参数会进行拷贝传给get_memory,这里假设拷贝之后的参数为_pStr,执行malloc之后,_pStr指向的是分配的堆空间,而pStr指向的仍然是NULL,所以使用pStr进行操作的时候,会报内存非法访问的错误,而此时,get_memory返回后,新分配的内存(_pStr所指向的空间)没发使用,还会导致内存泄露。
正确的用法为
-
-
-
-
-
-
-
-
- bool get_memory(char **pst, unsigned int size)
- {
- if (0 == size)
- {
- pst = NULL;
- return false;
- }
-
- (*pst) = (char*)malloc(size);
- if (NULL == *pst)
- {
- return false;
- }
- memset(*pst, 0, size);
-
- return true;
- }
-
- int use_get_memory()
- {
- char *pStr = NULL;
- char buf[] = "hello world.";
-
- if (get_memory(&pStr, 1024) == false)
- {
- return -1;
- }
- memcpy(pStr, buf, sizeof(buf));
-
- printf("%s\n", pStr);
-
- free(pStr);
- pStr = NULL;
-
- return 0;
- }
传入的是pStr的地址,进入函数后进行解引用操作,就是对pStr实际地址进行操作。