C语言:值传递,地址传递和引用传递(example:值交换)

于C语言中值传递、地址传递和引用传递的我个人理解。

通过一个例子:swap(交换两个整型变量的值)来表现!

 1 #include <stdio.h>
 2 void swap1(int* a,int* b);
 3 void swap2(int& a,int& b);
 4 void swap3(int* a,int* b);
 5
 6 void main(){
 7     printf("Hello World!\n");
 8     int a = 3;
 9     int b = 4;
10     printf("bef swap, add of a = %d\n",&a);
11     printf("aft swap, val of a = %d\n",a);
12     //swap(a,b);
13     swap1(&a,&b);
14     //swap2(a,b);
15     //swap3(&a,&b);
16
17     printf("aft swap, add of a = %d\n",&a);
18     printf("aft swap, val of a = %d\n",a);
19 }
20 // pass by value
21 void swap(int a,int b){
22     int temp = a;
23     a = b;
24     b = temp;
25 }
26 // pass by address
27 void swap1(int* a,int *b){
28     int temp = *a;
29     *a = *b;
30     *b = temp;
31 }
32 // pass by reference
33 void swap2(int& a,int& b){
34     int temp = a;
35     a = b;
36     b = temp;
37 }
38 // pass by value ?
39 void swap3(int* a,int *b){
40     int* temp = a;
41     a = b;
42     b = temp;
43 }

上面的函数,四个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,即两个地址。所以现在分析函数体:

1 int temp = *a;//取出地址a的值,并赋值给整型变量temp
2 *a = *b;      //取出地址b的值,并将这个值赋给地址a指向的值
3 *b = temp;    //将temp的值赋给地址b所指向的值

  因此,我们看到,由于函数传入的是地址,而函数体内又对地址进行取值和赋值操作,所以相对应的地址的值发生了改变。但是地址并没有实际改变,从函数的输出来看,a的地址并不会改变。在C语言中,函数在运行的时候会对每个变量分配内存地址,分配之后只要变量不被销毁,这个地址不能改变。&a = &b;是无法编译通过的。

2,引用传递

  这个理解起来更简单,我们这样理解引用,引用是变量的一个别名,调用这个别名和调用这个变量是完全一样的。所以swap2的结果可以解释。值得注意的是,由于引用时别名,所以引用并不是一种数据类型,内存并不会给它单独分配内存,而是直接调用它所引用的变量。这个与地址传递也就是指针是不一样的(也就是说一个指针虽然指向一个变量,但是这个指针变量在内存中是有地址分配的),下面代码进行验证。

 1 void main(){
 2     printf("Hello World!\n");
 3     int a = 3;
 4     int b = 4;
 5     int* c = &a;//c是指向a的指针
 6     int& d = b;//d是b的引用,alias of b = d
 7     printf("val of a = %d\n",a);
 8     printf("add of a = %d\n",&a);
 9     printf("val of c = %d\n",c);
10     printf("add of c = %d\n",&c);
11     printf("val of b = %d\n",b);
12     printf("add of b = %d\n",&b);
13     printf("val of d = %d\n",d);
14     printf("add of d = %d\n",&d);
15 }

输出结果:

我们看到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的函数传递都是值传递。

时间: 2024-09-27 04:35:41

C语言:值传递,地址传递和引用传递(example:值交换)的相关文章

为什么 Java 只有值传递,但 C# 既有值传递,又有引用传递,这种语言设计有哪些好处?

为什么 Java 只有值传递,但 C# 既有值传递,又有引用传递,这种语言设计有哪些好处? http://www.zhihu.com/question/20628016 Java值传递的终极解释 http://developer.51cto.com/art/201103/251163.htm

java只有值传递,不存在引用传递

今天,我在一本面试书上看到了关于java的一个参数传递的问题: 写道 java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这一特性很是熟悉! 结果发现,我错了! 答案是: 值传递!Java中只有按值传递,没有按引用传递! 回家后我就迫不及待地查询了这个问题,觉得自己对java这么基础的问题都搞错实在太丢人! 综合网上的描述,我大概了解了是怎么回事,现在整理如下,如有不对之处望大神提出! 先来看一个作为程序员都熟悉的值传递

Java语言中的值传递与引用传递

Java应用程序中永远不会传递对象,而只会传递对象应用,因此,按对象引用传递. (1)      Int作为参数传递时,对形参值得修改不会影响到实参: (2)      StringBuffer作为参数时,对形参对象内容的修改影响到了实参. (3)      值传递只是传递了一个值的副本,对形参值得改变不会影响实参的值. (4)      引用传递,由于参数的地址也是以值是方式传递的,因此,无法改变实参的地址,只能改变实参地址指向的对象的值. (5)      String对象的传递,由于Str

JavaScript进阶(三) 值传递和引用传递

从C语言开始 有时候讲一些细节或是底层的东西,我喜欢用C语言来讲,因为用C更方便来描述内存里面的东西.先举一个例子,swap函数,相信有一些编程经验的人都见识过,声明如下,函数体我就不写了,各位脑补一下. void swap1(int a, int b); void swap2(int* a, int* b) 这里swap1是不能交换两个数的值的,swap2可以.那为什么呢?有教材会说,第一个是值传递,第二个是引用传递,传递的是指针,所以第二个可以.好吧,这个解释和没说一样,那下面我就来解释一下

C++函数的三种传递方式为:值传递、指针传递和引用传递

值传递: void fun(int x){ x += 5; //修改的只是y在栈中copy x,x只是y的一个副本,在内存中重新开辟的一块临时空间把y的值 送给了x:这样也增加了程序运行的时间,降低了程序的效率. } void main(void){ int y = 0; fun(y); cout<<\"y = \"<<y<<endl; //y = 0; } 指针传递: void fun(int *x){ *x += 5; //修改的是指针x指向的内

值传递,指针传递;引用传递(c++独有)本质

要理解值传递.指针传递和引用传递的区别,主要要理解函数的实参和形参,函数的作用域(自动变量.栈),内存的布局以及指针和引用的特点.这里主要总结三种参数传递方式使用的主要场合. 值传递:只给函数提供输入值,需要复制开销,大对象很少使用值传递. 指针传递:可以改变指针指向内容的值,但是不能改变指针本身,无需复制开销.如果需要改变指针本身,可以使用二重指针或者指针引用. 引用传递:除了提供输入值外,还返回操作结果,无需复制开销. #include<stdlib.h> //值传递,函数体内变量n是参数

JavaScript的值传递和引用传递

本文和大家分享的主要是javascript中值传递和引用传递相关内容,一起来看看吧,希望对大家学习javascript有所帮助. JavaScript有5种基本的数据类型,分别是:布尔.null.undefined.String和Number.这些基本类型在赋值的时候是通过值传递的方式.值得注意的是还有另外三种类型: Array.Function和Object,它们通过引用来传递.从底层技术上看,它们三都是对象. 基本数据类型 如果一个基本的数据类型绑定到某个变量,我们可以认为该变量包含这个基本

java中值传递和引用传递

本来今天刚学习的内容,然后去其他博客看了下,发现都吵起来了,就是名字原因,有的说java有值传递和引用传递,有的说引用传递本质就是值传递,我管你杂说的,只要自己理解好,代码知道运行结果就好了. 我用自己的话,自己的理解来解释下,反正都是自己写着玩,自己看的 值传递:传递的值,这个值以后怎么改变,源值不会发生改变的. 引用传递:将对象的引用地址传递过去,如果值发生改变,那么源值也发生改变. 代码如下: 值传递: public class Test1 { public static void mai

Java技术_Java千百问(0039)_引用传递和值传递有什么区别

点击进入_更多_Java千百问 1.什么是值传递 值传递,是将内存空间中某个存储单元中存放的值,传送给另一个存储单元.(java中的存储单元并不是物理内存的地址,但具有相关性) 例如: //定义了一个改变参数值的函数 public static void changeValue(int x) { ??x = x *2; } public class TestMain{ //调用该函数 int num = 5; System.out.println(num); changeValue(num);

【转载】C++ 值传递、指针传递、引用传递详解

原文链接:http://www.cnblogs.com/yanlingyin/ 值传递: 形参是实参的拷贝,改变形参的值并不会影响外部实参的值.从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入, 不能传出.当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递. 指针传递: 形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作 引用传递: 形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数