关于“指针的指针”的认识(值传递、指针传递区分)
【摘要】对于C语言的参数传递通常都是值传递,当传传递一个指针给函数的时,其实质上还是值传递。我们可以看以下常见的面试题:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void function1(int *v)
{v = (int *)malloc(sizeof(int));*v = 100;
}void main()
{int *v = NULL;function1(v);printf("%d\n",*v);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
分析:指针其实本质就是一个变量,存放的是地址,不过也是一个值罢了,只不过特殊一点。本段函数的被调函数就把这个值(也就是地址)拷贝了下来。被调函数执行了 v = (int *)malloc(sizeof(int)); 之后,这样一条语句主动申请一块内存,并把这块内存的地址返回给v ,悄然把地址修改啦。这时主函数和被调函数中的指针指向的东西没有半毛关系了,主函数中v还是NULL,所以……
1、指针传递与值传递
我们再来看以一个交换2个数的值的函数调用的代码:
void swap ( int *a, int *b ){int c;c = *a;*a = *b;*b = c;
}
int main(int argc, char **argv){int a,b;a = 16;b = 32;swap( &a, &b);return ( a - b );
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
分析:能够正常交换a,b的值,被调函数操作的*a变量解引用一下,其实它的地址和主调函数a是一样的。因此它们操作是在同一块内存区域,可以实现数值的交换。
下面贴出一个错误的代码:
void swap ( int *a, int *b ){int *temp;temp = NULL;temp = a;a = b;b = temp;
}
int main ( int argc, char **argv ){int a,b;a = 16;b = 32;swap(&a, &b);return ( a - b );
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
分析:这种方式按照理论上来说,是想通过调用swap函数,在swap函数内部,实现将交换&a,&b,即交换a和b的地址来达到目的。但是被调函数只是对a,b的地址进行拷贝,简单一点说其实就相当于值传递,即使被调函数再一次对a,b地址进行修改,对主调函数实参a,b地址是没有任何影响的。所以根本没有起到值交换目的的。所以上述代码是错误的,无法实现你想要的功能。
2、指针的指针
当我们用二级指针来实现上述功能的时候有就可以达到效果。
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void swap ( int **a, int **b ){int *tmp = NULL;tmp = *a;*a = *b;*b = tmp;
}int main ( int argc, char **argv ){ int x = 16; int y = 32; int *a = &x;int *b = &y;swap(&a, &b); printf("%d\n",*a-*b);getchar();return 0; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
分析:这个时候,你会发现就能实现达到交换的目的。我们通过操作中间桥梁(一级指针 *a)通过交换它们的值,实现数值交换。
3、指针的指针常见用途
双指针主要用在但我们想向一个A函数传递参数的时候,但是我们希望在A内部对参数做任何修改都能保存起来,那么就是用双指针吧。
举个例子;
我们在做链表的时候,我们肯定希望在用一个函数creatLink(…)函数来增加链表节点。那么我们可以有2种方法来实现
第一种,用一级指针
typedef struct node{......
}list;
node *create(list *l){list *head;head = l;malloc...//为节点申请内存空间......//操作return head;
}
int main(...){......list *listheadcreateList(listhead);....//以后的任何操作,我们都要考虑,我们是否拿到的是链表头指针,到底哪是链表波的头指针,我们是否要return下来返回链表头指针??
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
分析:这样做可以达到增加节点的目的,但是,在任何情况下,我们的操作都得死死地抓住头指针,也即是我们增加节点后,任何对链表长度的修改,我们都要 链表头指针返回,即 return head;所以,我们要通过这个函数最后获得头指针,抓住他,死死地抓住他,然后操作。
第二种方法:用双指针,也即是二级指针。
typedef struct node{......
}list;
void create(list **l){list *head;head = l;malloc...//为节点申请内存空间......//操作
}int main(...){......list *stcreateList(st)......
//以后的任何操作,不管是删除还是插入,我们不需要考虑,我们是否已经return head了,不需要,我们在任何情况下,对链表的操作都只需要使用st来完成,因为,st就是链表的头指针,不变,因为在申明st的时候,已经为st分配 一个地址空间,它是存在的,一直存在,直到main函数结束
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
这里有关于指针的指针两篇不错的博客,推荐给大家
深入理解双指针的两种用法
重新认识二级指针(Pointers to Pointers)
关于“指针的指针”的认识(值传递、指针传递区分)相关推荐
- 函数指针,指针函数,返回值为指针的函数
摘要: 在学习C语言时,一个比较容易混淆的概念就是函数指针.指针函数.返回值为指针的函数.本文将对这三个概念进行区分.指针函数就是返回值为指针的函数,两个本质上是同一事物,只是叫法不同.函数指针就是一 ...
- c语言指针官方解释_C语言中的指针解释了–它们并不像您想象的那么难
c语言指针官方解释 Pointers are arguably the most difficult feature of C to understand. But, they are one of ...
- C++指针详解(指针初始化与回收,常量与指针,引用与指针)
C++指针详解 1.指针的定义初始化以及回收 2.常量与指针 1)常量指针(常指针) 2)指针常量 3)总结 3.引用与指针 1.指针的定义初始化以及回收 指针是一个地址,这个地址内存放数据,这些数据 ...
- C专家编程--指针和数组(三) 值传递 指针传递 引用传递
可以先看下这两篇文章 http://blog.csdn.net/yusiguyuan/article/details/12357381 http://blog.csdn.net/yusiguyuan/ ...
- 指针作为函数的返回值
指针不但可以作为函数的参数进行传递,还可以作为函数的返回值,返回的指针即可以指向 任何数据类型的地址,也可以指向一维数组或者多维数组的地址 #include<iostream> using ...
- linux 不同进程间能否传递指针?(不能,虚拟地址进程私有,被不同进程映射到物理地址不同)
不能 为了实现虚拟地址空间各进程私有,每个进程都拥有自己的页目录和页表结构,对不同进程而言,页目录中的页目录项值(PDE),以及页表中的页表项值(PTE)都是不同的,因此相同的指针(虚拟地址)被不同的 ...
- C 函数传递指针参数注意事项
指针参数:这个问题也可以归结为内存泄漏.对于malloc的变量,free之后一定要置为NULL,这样我们就可以通过判断这个自增是否为NULL来编程.所以为了简单和不至于忘记最后的一个置NULL操作,我 ...
- 彻底搞定C指针-——第五篇:函数参数的传递
一. 三道考题 开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行--唉呀,谁扔我鸡蛋?) 1. 考题一:程序代码如下: void Exchg1(int x, int y) { in ...
- golang中值类型/指针类型的变量区别总结
转自:https://segmentfault.com/a/1190000012329213 值类型的变量和指针类型的变量 先声明一个结构体: type T struct {Name string } ...
- 【C语言学习笔记】26. 指针(3)指向指针的指针、传递指针给函数
前言 指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链.通常,一个指针包含一个变量的地址.当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置. ...
最新文章
- 2022-2028全球及中国呼吸麻醉消耗品行业研究及十四五规划分析报告
- 创建yum存储库;文件目录下存RPM包,不挂载镜像,不使用外网yum源;
- attachRouteMatched analysis
- hydra安装及使用
- undo log mysql_MySQL的redo log与undo log
- [Ogre] 创建Ogre项目的一劳永逸的简单办法
- python安装virtualenv_python安装virtualenv虚拟环境步骤图文详解
- u3d_shader_surface_shader_2
- 传奇服务器修改变量,课程列表-传奇服务端制作修改教程-4.3变量-学传奇
- Windows 7 系统封装文字版 精简教程笔记!
- 控制系统matlab仿真,控制系统MATLAB仿真作业
- 免费WiFi上网软件之WiFi共享精灵
- 计算机桌面的图片要点开才可以看,在桌面上的图片文件都不显示具体图片了 只能打开这个图片才能看到是哪张图片 请问怎么处理?...
- 「广州SEO优化」Google优化SEO关键词排名工具
- 2020TB618喵币挂机自动获取脚本(jsapp)
- Stacked Hourglass Networks 理解
- 前后端分离使用Spring Boot + el-upload 完成图片上传
- 论文阅读(5)栉水母利用涡流反弹动力学,胜过其他凝胶状的游泳者(2019)
- 史上最简单的软件破解——5行脚本代码完美破解99%的过期软件
- TFTLCD屏幕实验
热门文章
- inner join 和 exists 效率_19条效率至少提高3倍的MySQL技巧
- Mysql学习(二)之安装、开启自启、启动、重启、停止
- MySql学习19-----用户管理
- H5中canvas和svg绘图方式介绍
- Rancher2.0中邮件通知的设置
- select自定义箭头问题 。。。和一行内不同颜色的整体鼠标滑过变色
- 【page-monitor 前端自动化 上篇】初步调研
- 【JavaService】部署Java jar为Windows后台服务
- global cache cr request
- [转]Linux环境下段错误的产生原因及调试方法小结