值传递 引用传递(传地址,传引用)的区别
传值,是把实参的值赋值给行参 ,那么对行参的修改,不会影响实参的值。
传地址,是传值的一种特殊方式,只是他传递的是地址,不是普通的如int,那么传地址以后,实参和行参都指向同一个对象。
传引用,真正的以地址的方式传递参数, 传递以后,行参和实参都是同一个对象,只是他们名字不同而已,对行参的修改将影响实参的值。
从函数调用的角度比较容易理解:
- 函数的名字就是函数的首地址,就是函数的入口,例子:
void fun(void)
{}
既然 fun 是地址值,那么 fun 是什么类型? 指针类型,因为它的本质是一个地址。
void ( *)(void)
—> void fun(void)
int fun2(short s, int i){return 0;}↓int (*)(short, int) //fun2的类型函数调用: fun2(10,20);int (*p)(short, int) = fun2;
将 fun2 赋值给其他值:p = fun2,因为fun2的本质是一个地址,所以接收类型应该是:int (*)(short,int) p = fun2;
<— 然而,并没有这样的写法。这里有一个规律,如果你看见 (*)
单独存在,要将后面的东西放入到 *
的后面,即 写法为: int ( *p)(short, int) = fun2;
因为将fun2的值赋值给了 p,所以下面两种调用是一致的:
p(10,20); // fun2(10,20);
- 形参
void fun(short s, int *p){}short a = 10;int b = 20;fun(a, &b);
值传递 : 将变量的值,直接传给形参 // 比如 a 址传递 : 将变量的地址,传给形参 // 比如 &b
void fun(int x, int *p){}int a = 10;int b = 20;int *xp = &b;fun(a, xp); // xp 是一个 值传递 而相对于 b 来说,这才是一个址传递
#include <stdio.h>int fun(int x, int y);
int main(void)
{int a = 10, b = 20;fun(a, b); //调用fun函数 --> 在内存中给 fun 函数开辟空间printf("%d %d\n", a, b); //a,b 没有变化,因为CPU的寄存器中,fun值传递后,内存被释放,a,b的值不变fun2(&a); // 址传递,获取到了a空间中存储的值,在内存中开辟fun2 空间,p 指针类型(32位 4个字节/64位 8个字节)printf("a:%d b:%d\n", a, b); // 300 20 // *&x ---> x return 0;
}int fun(int x, int y)
{x = 100;y = 200;return x+y;
}void fun2(int *p)
{*p = 300; //地址传递,指针 p 解引用可以获取到这个指针指向的对应的空间,它可以改变函数外面的某一个变量 传递结束后,fun2 被释放
}
//因此 scanf("%d",&a); 函数中的传参是取地址传递,与上述 fun2 同理,因为值传递内存释放后原有的数值不发生改变 而地址传递会获取到“房间”中的值,并改变这个地址中存储的内容