C语言:值传递,地址传递和引用传递(example:值交换)
于C语言中值传递、地址传递和引用传递的我个人理解。
通过一个例子:swap(交换两个整型变量的值)来表现!
#include <stdio.h>
void swap1(int* a,int* b);
void swap2(int& a,int& b);
void swap3(int* a,int* b); void main(){
printf("Hello World!\n");
int a = ;
int b = ;
printf("bef swap, add of a = %d\n",&a);
printf("aft swap, val of a = %d\n",a);
//swap(a,b);
swap1(&a,&b);
//swap2(a,b);
//swap3(&a,&b); printf("aft swap, add of a = %d\n",&a);
printf("aft swap, val of a = %d\n",a);
}
// pass by value
void swap(int a,int b){
int temp = a;
a = b;
b = temp;
}
// pass by address
void swap1(int* a,int *b){
int temp = *a;
*a = *b;
*b = temp;
}
// pass by reference
void swap2(int& a,int& b){
int temp = a;
a = b;
b = temp;
}
// pass by value ?
void swap3(int* a,int *b){
int* temp = a;
a = b;
b = temp;
}
上面的函数,四个swap函数,输出结果:
swap(a,b):

swap1(a,b):

swap2(a,b):

swap3(a,b):

我们看到,真正起作用的是swap1和swap2.这两个分别是地址传递和引用传递。swap是典型的值传递,swap3是什么我后面会讲。
分析!
0,值传递
这个比较简单,实参a 原本指向地址 1638212,代表1638212这个地址的值是3。在swap函数中,实参a将值拷贝给形参a,形参a此时也在内存中拥有地址,地址= xxxx,值为3,在所有的函数体内的操作,都是对 xxxx这个地址的操作,所以并不会影响实际参数的值。
1,地址传递
这个对于理不清指针是什么的同学来说比较难。在这里我们习惯把指针写成int* a,int* b而不是int *a,int *b。我们可以这样理解:指针是一种特殊的数据类型,若 int c = 5;int* a = &c;则a是一个指针变量,它的值是c的地址!星号“*”是一个取值操作,和号“&”是一个取址操作。所以此时单纯看a和b都是一个整数,它们表示地址,进行取值操作之后就可以得到相应地址的值。函数接受两个类型为指针的变量,实际接受的是a和b,即两个地址。所以现在分析函数体:
int temp = *a;//取出地址a的值,并赋值给整型变量temp
*a = *b; //取出地址b的值,并将这个值赋给地址a指向的值
*b = temp; //将temp的值赋给地址b所指向的值
因此,我们看到,由于函数传入的是地址,而函数体内又对地址进行取值和赋值操作,所以相对应的地址的值发生了改变。但是地址并没有实际改变,从函数的输出来看,a的地址并不会改变。在C语言中,函数在运行的时候会对每个变量分配内存地址,分配之后只要变量不被销毁,这个地址不能改变。&a = &b;是无法编译通过的。
2,引用传递
这个理解起来更简单,我们这样理解引用,引用是变量的一个别名,调用这个别名和调用这个变量是完全一样的。所以swap2的结果可以解释。值得注意的是,由于引用时别名,所以引用并不是一种数据类型,内存并不会给它单独分配内存,而是直接调用它所引用的变量。这个与地址传递也就是指针是不一样的(也就是说一个指针虽然指向一个变量,但是这个指针变量在内存中是有地址分配的),下面代码进行验证。
void main(){
printf("Hello World!\n");
int a = ;
int b = ;
int* c = &a;//c是指向a的指针
int& d = b;//d是b的引用,alias of b = d
printf("val of a = %d\n",a);
printf("add of a = %d\n",&a);
printf("val of c = %d\n",c);
printf("add of c = %d\n",&c);
printf("val of b = %d\n",b);
printf("add of b = %d\n",&b);
printf("val of d = %d\n",d);
printf("add of d = %d\n",&d);
}
输出结果:

我们看到c的值是a的地址,c的地址是单独分配的;而d的值是b的值,d的地址是b的地址!
4,关于swap3怎么解释。
我认为swap3是一种值传递,如果我们把int*完全当做跟int一个级别的数据类型,那么swap3和swap两个函数是一摸一样的。只不过后者传入的是变量a,b的拷贝值,而后者传入的是变量a,b的地址的拷贝值;前者不能反应在外部,后者也不能。
最后,我们注意,对于应用,如果我们有代码:int a = 3; int& b = a;(b is an alias of a)b = 10;那么我们会发现a的值此时也变成了10。
但是在java中,如果我们把java的引用简单想象成这里的引用,是有问题的。因为如果一个函数出入一个对象Person person = new Person("ZHANG San"),而在函数体内进行这个操作:person = new Person("LI Si");那么person的值并不能被改变,所以我们说java的函数传递都是值传递。
C语言:值传递,地址传递和引用传递(example:值交换)的更多相关文章
- ECMAScript中所有参数传递的都是值,不可能通过引用传递参数
今天在看JavaScript高级程序设计(第三版)时,看到了这个问题:ECMAScript中所有参数传递的都是值,不可能通过引用传递参数. 在我的印象中,其他语言比如Java,C++等,传递参数有两种 ...
- Java语言对对象采用的是引用传递还是按值传递?
按值调用表示方法接收的是调用者提供的值:而按引用调用表示方法接收的是调用者提供的变量地址:一个方法可以修改传递引用所对应的变量值, 而不能修改传递值调用所对应的变量值: Java语言对对象采用的是引用 ...
- java只有值传递,不存在引用传递
今天,我在一本面试书上看到了关于java的一个参数传递的问题: 写道 java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这 ...
- 如何形象简单地理解java中只有值传递,而没有引用传递?
首先,java中只有值传递,没有引用传递.可以说是"传递的引用(地址)",而不能说是"按引用传递". 按值传递意味着当将一个参数传递给一个函数时,函数接收的是原 ...
- Java的参数传递是「值传递」还是「引用传递」?
关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题. 有人说Java中只有值传递,也有人说值传递和引用传递都是存在的,比较容易让人产生疑问. 关于值传递和引用传递其实需要分情况看待. ...
- Java语言中的值传递与引用传递
Java应用程序中永远不会传递对象,而只会传递对象应用,因此,按对象引用传递. (1) Int作为参数传递时,对形参值得修改不会影响到实参: (2) StringBuffer作为参 ...
- JavaScript进阶(三) 值传递和引用传递
从C语言开始 有时候讲一些细节或是底层的东西,我喜欢用C语言来讲,因为用C更方便来描述内存里面的东西.先举一个例子,swap函数,相信有一些编程经验的人都见识过,声明如下,函数体我就不写了,各位脑补一 ...
- Java中到底是值传递还是引用传递?
Java中到底是值传递还是引用传递? 我们先回顾一下基本概念 实参和形参 参数在编程语言中是执行程序需要的数据,这个数据一般保存在变量中.在Java中定义一个方法时,可以定义一些参数, 举个例子: p ...
- 面试官:兄弟,说说Java到底是值传递还是引用传递
二哥,好久没更新面试官系列的文章了啊,真的是把我等着急了,所以特意过来催催.我最近一段时间在找工作,能从二哥的文章中学到一点就多一点信心啊! 说句实在话,离读者 trust you 发给我这段信息已经 ...
- 多图证明,Java到底是值传递还是引用传递?
开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见正文. 说到值传递和引用传递我们不得不提到两个概念:值类型和引用类型. 1.值类型 通俗意义上来说,所谓的值类型指的就 ...
随机推荐
- Docker配置daocloud加速器
首先注册daocloud网站的账号(免费的!!!),并登陆自己的账号,并在这里获取自己的daocloud加速器配置脚本. 获取到自己的daocloud加速器配置脚本之后只需要在已安装Docker服务的 ...
- 我的菜单在母版页,如何更改菜单点击后的效果 Ver2
很久之前,Insus.NET使用ASP.NET实现一个功能,非javascript.<我的菜单在母版页,如何更改菜单点击后的效果>http://www.cnblogs.com/insus/ ...
- SpringBoot整合Druid数据连接池
SpringBoot整合Druid数据连接池 Druid是什么? Druid是Alibaba开源的的数据库连接池.Druid能够提供强大的监控和扩展功能. 在哪里下载druid maven中央仓库: ...
- Java - "JUC线程池" 线程状态与拒绝策略源码分析
Java多线程系列--“JUC线程池”04之 线程池原理(三) 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基本概念"中,我们介绍过,线程有5种状态:新建 ...
- 初识Java作业
初识Java作业 一. 填空题 Java技术按照用途不同分为三大版本,分别是JavaSE. javaEE 和JavaMe Java虚拟机就是一个虚拟的用于执行 .class ...
- Onsen UI for React文档
注:采用ES6+JSX语法 1.开始一个项目 在React中使用Onsen UI 需要首先安装onsenui和react-onsenui模块. 可以使用monaca CLI工具包快速初始化一个应用: ...
- mysql数据库操作指令
数据库相关 查询所有数据库 show databases; 创建数据库 create database 数据库名: 创建数据库指定字符集 create database 数据库名 character ...
- [基础知识]在PeopleSoft中SMTP设置不生效如何查找问题
在PeopleSoft中如果配置了工作流邮件或者标准页面的通知,都是可以发送出邮件的,这些邮件都是由SMTP服务器发送.SMTP需要在APP服务器和PRCS服务器中配置. 如果无法从PeopleSof ...
- 用ContentProvider获取通讯录联系人
手机中的联系人数据实际是保存在数据库中的,但Android并没有让我们通过操作数据库去读取数据,而是通过一个ContractProvider这个应用提供了一个ContentProvider访问接口. ...
- JavaScript数组转字符串,字符串转数组
//--------------------数组转字符串--------------------------- //需要将数组元素用某个字符连接成字符串 var a1, b1,c1; a1 = [&q ...