【摘要】对于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)

关于“指针的指针”的认识(值传递、指针传递区分)相关推荐

  1. 函数指针,指针函数,返回值为指针的函数

    摘要: 在学习C语言时,一个比较容易混淆的概念就是函数指针.指针函数.返回值为指针的函数.本文将对这三个概念进行区分.指针函数就是返回值为指针的函数,两个本质上是同一事物,只是叫法不同.函数指针就是一 ...

  2. c语言指针官方解释_C语言中的指针解释了–它们并不像您想象的那么难

    c语言指针官方解释 Pointers are arguably the most difficult feature of C to understand. But, they are one of ...

  3. C++指针详解(指针初始化与回收,常量与指针,引用与指针)

    C++指针详解 1.指针的定义初始化以及回收 2.常量与指针 1)常量指针(常指针) 2)指针常量 3)总结 3.引用与指针 1.指针的定义初始化以及回收 指针是一个地址,这个地址内存放数据,这些数据 ...

  4. C专家编程--指针和数组(三) 值传递 指针传递 引用传递

    可以先看下这两篇文章 http://blog.csdn.net/yusiguyuan/article/details/12357381 http://blog.csdn.net/yusiguyuan/ ...

  5. 指针作为函数的返回值

    指针不但可以作为函数的参数进行传递,还可以作为函数的返回值,返回的指针即可以指向 任何数据类型的地址,也可以指向一维数组或者多维数组的地址 #include<iostream> using ...

  6. linux 不同进程间能否传递指针?(不能,虚拟地址进程私有,被不同进程映射到物理地址不同)

    不能 为了实现虚拟地址空间各进程私有,每个进程都拥有自己的页目录和页表结构,对不同进程而言,页目录中的页目录项值(PDE),以及页表中的页表项值(PTE)都是不同的,因此相同的指针(虚拟地址)被不同的 ...

  7. C 函数传递指针参数注意事项

    指针参数:这个问题也可以归结为内存泄漏.对于malloc的变量,free之后一定要置为NULL,这样我们就可以通过判断这个自增是否为NULL来编程.所以为了简单和不至于忘记最后的一个置NULL操作,我 ...

  8. 彻底搞定C指针-——第五篇:函数参数的传递

    一. 三道考题 开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行--唉呀,谁扔我鸡蛋?) 1. 考题一:程序代码如下: void Exchg1(int x, int y)   {   in ...

  9. golang中值类型/指针类型的变量区别总结

    转自:https://segmentfault.com/a/1190000012329213 值类型的变量和指针类型的变量 先声明一个结构体: type T struct {Name string } ...

  10. 【C语言学习笔记】26. 指针(3)指向指针的指针、传递指针给函数

    前言 指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链.通常,一个指针包含一个变量的地址.当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置. ...

最新文章

  1. 2022-2028全球及中国呼吸麻醉消耗品行业研究及十四五规划分析报告
  2. 创建yum存储库;文件目录下存RPM包,不挂载镜像,不使用外网yum源;
  3. attachRouteMatched analysis
  4. hydra安装及使用
  5. undo log mysql_MySQL的redo log与undo log
  6. [Ogre] 创建Ogre项目的一劳永逸的简单办法
  7. python安装virtualenv_python安装virtualenv虚拟环境步骤图文详解
  8. u3d_shader_surface_shader_2
  9. 传奇服务器修改变量,课程列表-传奇服务端制作修改教程-4.3变量-学传奇
  10. Windows 7 系统封装文字版 精简教程笔记!
  11. 控制系统matlab仿真,控制系统MATLAB仿真作业
  12. 免费WiFi上网软件之WiFi共享精灵
  13. 计算机桌面的图片要点开才可以看,在桌面上的图片文件都不显示具体图片了 只能打开这个图片才能看到是哪张图片 请问怎么处理?...
  14. 「广州SEO优化」Google优化SEO关键词排名工具
  15. 2020TB618喵币挂机自动获取脚本(jsapp)
  16. Stacked Hourglass Networks 理解
  17. 前后端分离使用Spring Boot + el-upload 完成图片上传
  18. 论文阅读(5)栉水母利用涡流反弹动力学,胜过其他凝胶状的游泳者(2019)
  19. 史上最简单的软件破解——5行脚本代码完美破解99%的过期软件
  20. TFTLCD屏幕实验

热门文章

  1. inner join 和 exists 效率_19条效率至少提高3倍的MySQL技巧
  2. Mysql学习(二)之安装、开启自启、启动、重启、停止
  3. MySql学习19-----用户管理
  4. H5中canvas和svg绘图方式介绍
  5. Rancher2.0中邮件通知的设置
  6. select自定义箭头问题 。。。和一行内不同颜色的整体鼠标滑过变色
  7. 【page-monitor 前端自动化 上篇】初步调研
  8. 【JavaService】部署Java jar为Windows后台服务
  9. global cache cr request
  10. [转]Linux环境下段错误的产生原因及调试方法小结