值传递和引用传递最熟悉的例子应该是两个参数的交换了,我们知道值传递中对形参的修改不会影响实参,引用传递中对形参的修改会作用于实参。那么为什么会这样呢?
值传递的例子
#include <stdio.h>
#include <stdlib.h>
void change(int value)
{
value = 10;
}
int main()
{
int a = 5;
change(a);
printf("%d\n",a);
return 0;
}
引用传递的例子
#include <stdio.h>
#include <stdlib.h>
void change(int *pValue)
{
*pValue= 10;
}
int main()
{
int a = 5;
change(&a);
printf("%d\n",a);
return 0;
}
结果大家都知道,值传输出5,引用传输出10;
在值传递过程中,实参和形参位于内存中两个不同地址中,实参先自己复制一次拷贝,再把拷贝复制给形参。所以,在值传递过程中,形参的变化不会对实参有任何的影响。
这么说很抽象,大家可以理解为在函数调用的过程中有如下默认过程:
值传递中调用change函数等价于
int change(int value)
{
value = a; //main中调用change(a)等价于把a的副本赋值给value;
value = 10;
}
函数结束后局部变量value失效,显然对value的改变不会影响到main中的变量a;
引用传递中调用change函数等价于
int change(int *pValue)
{
pValue = &a; //main中调用change(&a)等价于把a的地址赋值给指针pValue;
*pValue = 10;
}
通过指针pValue操作main中的变量a,所以对pValue的修改作用于main中的变量a
可见虽然函数调用过程中,形参的值都是实际参数的副本,但是值传递得到的是变量值的副本,引用传递得到的是变量地址的副本。
以此做个推广,既然指针表示的是地址,那么把指针作为参数调用函数就会修改指针的值吗?如下:
指针作为参数申请内存
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
void myMalloc(int *address,const int size)
{
address = (int *)malloc(sizeof(int) * size);
}
int main()
{
int *p = NULL;
myMalloc(p,100);
printf("%p\n",p);
return 0;
}
myMalloc函数传入的参数是一个地址和要申请的内存的大小,那么这段代码执行完毕后main中的p是不是如愿以偿的分配到了内存呢?答案是否。
main调用myMalloc申请内存等价于
void myMalloc(int *address,const int size)
{
address = p; //把main中p的值赋值给address;
address = (int *)malloc(sizeof(int) * size);
}
myMalloc中只是对局部变量address做了修改,这个变量跟main中的变量p的唯一关系是它被p的副本赋了初始值。所以对address的修改不会影响到main函数中的变量p。打印结果p仍然为空指针。
最后总结一下:
函数调用过程中,如果要在被调函数中计算或处理主调函数中的变量的值,使用值传递;如果要在被调函数中改变主调函数中的变量,那么要用引用传递。