(十二)C语言双指针的常见用法
1、用作函数的返回值,比较常见的是返回分配的堆内存地址。
下面用一个例子进行说明下:
/*****************************************************************************/
/**
* \brief 分配指定大小size的堆空间
* \param[out] pst 分配的内存的地址
* \param[in] size 需要分配的内存大小
* \return 返回值描述
* \remarks 其它信息
******************************************************************************/
bool get_memory(char *pst, unsigned int size)
{
if ( == size)
{
pst = NULL;
return false;
} pst = (char*)malloc(size);
if (NULL == pst)
{
return false;
}
memset(pst, , size); return true;
} int use_get_memory()
{
char *pStr = NULL;
char buf[] = "hello world.";
get_memory(pStr, ); memcpy(pStr, buf, sizeof(buf)); return ;
}
当我们运行这段程序的时候,会发现程序崩溃了,出错的原因是对内存的非法访问,为什么会出现这种情况呢,我们明明已经分配了内存的啊,那我们就进行调试一下,看看问题究竟出现在哪里。
发现调用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 ( == size)
{
pst = NULL;
return false;
} (*pst) = (char*)malloc(size);
if (NULL == *pst)
{
return false;
}
memset(*pst, , size); return true;
} int use_get_memory()
{
char *pStr = NULL;
char buf[] = "hello world."; if (get_memory(&pStr, ) == false)
{
return -;
}
memcpy(pStr, buf, sizeof(buf)); printf("%s\n", pStr); free(pStr);
pStr = NULL; return ;
}
传入的是pStr的地址,进入函数后进行解引用操作,就是对pStr实际地址进行操作。
2、用于申请动态一维数组,只是这个一维数组中存储的是指针类型。
一维数组中的每个指针又可以动态分配一个一维数组,即最终可以形成一个二维数组。
int** array_init(unsigned int size)
{
int **ppArray = NULL;
if ( == size)
{
return NULL;
} ppArray = (int**)malloc(sizeof(int*) * size);
if (ppArray == NULL)
{
return NULL;
}
memset(ppArray, , sizeof(int*) * size); return ppArray;
} void use_array()
{
int **ppArr = NULL;
int i = ;
ppArr = array_init(); int array[] = { , , , , , , , , , };
for (i = ; i < ; i++)
{
ppArr[i] = &array[i];
} for (int i = ; i < ; 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语言双指针的常见用法的更多相关文章
- Java开发笔记(四十二)日历工具的常见应用
前面介绍了日历工具Calendar的基本用法,乍看起来Calendar与Date两个半斤八两,似乎没有多大区别,那又何苦庸人自扰鼓捣一个新玩意呢?显然这样小瞧了Calendar,其实它的作用大着呢,接 ...
- python接口自动化(三十二)--Python发送邮件(常见四种邮件内容)番外篇——上(详解)
简介 本篇文章与前边没有多大关联,就是对前边有关发邮件的总结和梳理.在写脚本时,放到后台运行,想知道执行情况,会通过邮件.SMS(短信).飞信.微信等方式通知管理员,用的最多的是邮件.在linux下, ...
- [转]Java程序员从笨鸟到菜鸟之(八十三)细谈Spring(十二)OpenSessionInView详解及用法
首先我们来看一下什么是OpenSessionInView? 在hibernate中使用load方法时,并未把数据真正获取时就关闭了session,当我们真正想获取数据时会迫使load加载数据,而 ...
- 03--(二)编程实践中C语言的一些常见细节
编程实践中C语言的一些常见细节(转载) 对于C语言,不同的编译器采用了不同的实现,并且在不同平台上表现也不同.脱离具体环境探讨C的细节行为是没有意义的,以下是我所使用的环境,大部分内容都经过测试,且所 ...
- C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com
原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | I ...
- C语言库函数大全及应用实例十二
原文:C语言库函数大全及应用实例十二 [编程资料]C语言库函数大全及应用实例十二 函数名: setrgbpalette ...
- layui(二)——layer组件常见用法总结
layer是layui的代表作,功能十分强大,为方便以后快速配置这里对其常见用法做了简单总结 一.常用调用方式 //1.普通消息:alert(content,[options],[yesCallBac ...
- C语言第十二讲,文件操作.
C语言第十二讲,文件操作. 一丶文件操作概述 在操作系统中,我们的文档都称为文件.操作系统也为我们提供了接口进行操作.不同语言都是使用的相同的接口,只不过封装的上层接口不一样 操作文件的步骤 打开文件 ...
- Go语言学习笔记十二: 范围(Range)
Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...
随机推荐
- ESP-01S-ESP8266入门教程
1.模块实物 2.引脚说明 3.连接说明,按下图将引脚连接到PC的串口(VCC接3V,GND接地,TX接串口TX,RX接串口的RX,CH_PD接3V,否则wifi不工作) 4.通过该PC串口配置WiF ...
- 菜鸟教程perl总结
数据类型有: 标量$, 数组@,哈希% 数组声明 : @hits = (25, 30, 40); 或者 @sites = qw/google taobao runoob/; 数组操作 pop, ...
- wlr设置 Blog Ping
ref:http://www.cnblogs.com/zhangyang/archive/2011/07/22/2113856.html 设置 Blog Ping 1.什么是Ping服务(Ping S ...
- 大数据江湖之即席查询与分析(下篇)--手把手教你搭建即席查询与分析Demo
上篇小弟分享了几个“即席查询与分析”的典型案例,引起了不少共鸣,好多小伙伴迫不及待地追问我们:说好的“手把手教你搭建即席查询与分析Demo”啥时候能出?说到就得做到,差啥不能差人品,本篇只分享技术干货 ...
- WPF的线程模型
原文:WPF的线程模型 WPF的线程模型 周银辉 谈到多线程,很多人对其可能都不太有好感,觉得麻烦与易出错.所以我们不排除有这样的情况:假设我对“多线程”.“异步”这些字眼潜意识 ...
- long转int
由int类型转换为long类型是向上转换,可以直接进行隐式转换,但由long类型转换为int类型是向下转换,可能会出现数据溢出情况: 主要以下几种转换方法,供参考: 一.强制类型转换 [java] l ...
- 远程 RADIUS 服务器组
远程 RADIUS 服务器组 远程 RADIUS 服务器组是包含一个或多个 RADIUS 服务器的已命名的组.IAS 用作 RADIUS 请求消息的 RADIUS 代理时,必须指定远程 RADIUS ...
- Canvas 给图形绘制阴影
/** * 图形绘制阴影 */ function initDemo6() { var canvas = document.getElementById("demo6"); if ( ...
- 3dMax,Maya与FBX
3DMax下载地址(包含安装教程与注册方法):http://www.3d66.com/popsoft_1.html 3DMax已经自带导出为fbx格式的功能,所以无需安装fbx插件 Maya下载地址( ...
- sql 游标使用
declare @PASSDate datetime,@VLPN varchar(50),@VLPNColor varchar(10),@nambers int set @VLPN='';set @V ...