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.值类型 通俗意义上来说,所谓的值类型指的就 ...
随机推荐
- (微信小程序)一 : 初识微信小程序
首先看过angularjs的同学们在看微信小程序的创始文件应该不算很陌生吧. 需要看的 先是文件目录 看完这个目录..得知 ( 一 ) pages 他存放于多个页面 如 index ,log ...
- SQL server Profiler 监视数据库活动
做网站后台开始时需要考虑后台对数据库的一些操作,比如尽量减少查询次数,尽快释放连接,只选取必须的字段等等.如果是用三层开发,复杂的项目中直接拼装SQL语句多一点,拼装的SQL语句可以直接在SQL se ...
- [基础篇] 玄机网C#培训课程-初级.
课程目录 0x01第一课课前准备vs的选择与安装常用工具/网址 http://msdn.itellyou.cn/vs常用设置 0x02第二课C#的语法样式 编程风格VS的常用功能 俩个注意 ...
- Power of Matrix(uva11149+矩阵快速幂)
Power of Matrix Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit St ...
- SqlSession对象之Executor
Executor是Mybatis的一个核心接口,每一个SqlSession对象都会拥有一个Executor(执行器对象):这个执行对象负责[增删改查]的具体操作,我们可以简单的将它理解为JDBC中St ...
- POJ3090(SummerTrainingDay04-M 欧拉函数)
Visible Lattice Points Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7450 Accepted: ...
- zsh: command not found cnpm,gulp等命令在zsh终端上报错的问题
以cnpm包为例,使用 npm install -g cnpm 创建了cnpm包.而在zsh终端上运行cnpm,出现 zsh: command not found: cnpm 的报错.同样的,gulp ...
- sublime3 常用快捷键
轻量级编辑器,一直用的sublime text3 , 可以根据自己喜好安装喜欢的风格插件,根据工作需求安装代码处理插件. 下一章将推荐我常用的一些风格与代码插件 这里记录一些sublime 常用的快捷 ...
- 【读书笔记】iOS-报刊杂志-Newsstand应用编程
一,使用Newsstand Kit API 苹果公司在iOS5之后提供了电子报刊杂志开发API-Newsstand Kit.Newsstand Kit 只有3个类:NKLibrary,NKIssue和 ...
- eclipse导入web项目报错
主要是用svn Checkout一个web项目,然后导入eclipse中运行.正常情况应该是没什么问题的,但是有时候也会有点题.是看了别人的博客之后,确实解决了问题,就记录一下.因为很多坑,要自己掉过 ...