C语言双指针的常见用法
2015-10-30 10:19
423 查看
鉴于工作经验有限,目前遇到的双指针的用法有如下几种情况,后续工作中如发现有其他的用法,会更新上去。
1、用作函数的返回值,比较常见的是返回分配的堆内存地址。
下面用一个例子进行说明下:
![](http://img.blog.csdn.net/20151030090559970?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
发现调用get_memory函数之后,pStr所指向的内存竟然是空的,可见问题就出现在这里。
函数参数的传递是按值传递的,指针类型的参数其实也是按值进行传递的,只不过传递的是变量的地址,按值传递会进行拷贝,下面用一个图进行解释。
![](http://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所指向的空间)没发使用,还会导致内存泄露。
正确的用法为
![](http://img.blog.csdn.net/20151030093231407?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
传入的是pStr的地址,进入函数后进行解引用操作,就是对pStr实际地址进行操作。
2、用于申请动态一维数组,只是这个一维数组中存储的是指针类型。
一维数组中的每个指针又可以动态分配一个一维数组,即最终可以形成一个二维数组。
3、表示指针的地址,即指向指针的指针。
这里举个双向队列TAILQ的结构定义中使用的双指针。
1、用作函数的返回值,比较常见的是返回分配的堆内存地址。
下面用一个例子进行说明下:
/*****************************************************************************/ /** * \brief 分配指定大小size的堆空间 * \param[out] pst 分配的内存的地址 * \param[in] size 需要分配的内存大小 * \return 返回值描述 * \remarks 其它信息 ******************************************************************************/ 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的调试截图如下:
发现调用get_memory函数之后,pStr所指向的内存竟然是空的,可见问题就出现在这里。
函数参数的传递是按值传递的,指针类型的参数其实也是按值进行传递的,只不过传递的是变量的地址,按值传递会进行拷贝,下面用一个图进行解释。
调用get_memory后,pStr参数会进行拷贝传给get_memory,这里假设拷贝之后的参数为_pStr,执行malloc之后,_pStr指向的是分配的堆空间,而pStr指向的仍然是NULL,所以使用pStr进行操作的时候,会报内存非法访问的错误,而此时,get_memory返回后,新分配的内存(_pStr所指向的空间)没发使用,还会导致内存泄露。
正确的用法为
/*****************************************************************************/ /** * \brief 分配指定大小size的堆空间 * \param[out] pst 分配的内存的地址 * \param[in] size 需要分配的内存大小 * \return 返回值描述 * \remarks 其它信息 ******************************************************************************/ 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实际地址进行操作。
2、用于申请动态一维数组,只是这个一维数组中存储的是指针类型。
一维数组中的每个指针又可以动态分配一个一维数组,即最终可以形成一个二维数组。
int** array_init(unsigned int size) { int **ppArray = NULL; if (0 == size) { return NULL; } ppArray = (int**)malloc(sizeof(int*) * size); if (ppArray == NULL) { return NULL; } memset(ppArray, 0, sizeof(int*) * size); return ppArray; } void use_array() { int **ppArr = NULL; int i = 0; ppArr = array_init(10); int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; for (i = 0; i < 10; i++) { ppArr[i] = &array[i]; } for (int i = 0; i < 10; i++) { printf("%d\n", *(int*)(ppArr[i])); } }
3、表示指针的地址,即指向指针的指针。
这里举个双向队列TAILQ的结构定义中使用的双指针。
#define TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ }这是TAILQ对两个指向前后两个元素指针的抽象,抽象为TAILQ_ENTRY结构体:tqe_next是指向下一个元素的指针,tqe_prev是一个二级指针,指针变量的地址,是前一个元素的tqe_next的地址,解引用(*tqe_prev)之后就是本元素的内存地址。
相关文章推荐
- c语言const、volatile问题小结
- C++析构函数
- VS2005 中C++文件无法设置断点调试
- c++中.dll与.lib文件的生成与使用的详解
- C++实现逐行从文本文件读取数据
- c++分数加减乘除
- C++ API 设计 之 “++”
- iOS开发笔记-xcode7编译错误之缺少libc++.dylib
- C语言开发环境配置
- 免费的C++数学运算库
- 免费的C++数学运算库
- C++11中的原子操作(atomic operation)
- GCC在C语言中内嵌汇编 asm __volatile__
- C,C++宏中#与##的讲解
- C++之tinyXML使用
- C++基础
- 第8周项目2 建立链串的算法库
- c++boost中的asio介绍
- 二叉搜索树(Binary Search Tree)--C语言描述(转)
- C++指针和数组:字符和字符串、字符数组