C中的直接间接值传递&C++中的引用传递
C语言中所有的实参都是按值传递,可以使用取地址和间接寻址实现引用传递。
C其实只有值传递,另外C也没有引用这种东西。
理论上,可以将C语言中的参数传递方式都称为值传递。值传递,故名思意,传递的是参数的值,而不是参数本身。例如:
int main()
{
int a = 1, b = 2;
printf("before a = %d b = %d\n", a, b); //输出交换前a,b的值
swap(a, b);
printf("after a = %d b = %d\n", a, b); //输出交换后a,b的值
return 0;
}
对于该主函数来说,定义a,b的过程,实际上分配了两个4字节(int型变量)的存储空间,分别名为为a和b的,并将其赋值为1和2。接下来,分别编写不同的swap函数,来验证他们的不同之处。
C值传递方式一:传数(直接)
void swap(int x, int y) //将a,b的值传递给函数
{
int temp;
temp = x;
x = y;
y = temp;
}
使用swap(a, b);
调用该函数时,只是单纯的将a和b的值传递给x和y,可以将x和y理解为是a和b的副本。从本质上说,x,y是局部变量,在调用函数时,函数实际上会在栈中分配两个临时的的空间,并命名为x和y,局部变量仅存在于函数执行的过程中,当函数返回后,分配的空间就会被释放。
在调用函数的过程中,还会把传入的参数的值赋给该局部变量。在本例中,就是将a的值1赋给x,将b的值2赋给y。在函数执行的过程中,实际上处理的都是x和y,而不会改变a和b的值(x,y和a,b分别存储在不同的地址空间中)。
运行结果应当为:
before a = 1 b = 2
after a = 1 b = 2
C值传递方式二:传地址(间接)
void swap(int *x, int *y) //将a,b的地址传递给函数
{
int temp;
temp = *x;
*x = *y;
y = temp;
}
这是初学C语言时,所学习的引用传递,但是,从本质上来讲,这仍然是值传递。
使用swap(&a, &b);
调用该函数时,实际上是将a和b存储空间的地址传递给局部变量x和y,也就是说,此时,名为x的临时空间中存储的是a的地址,而函数中的*x
则是指针x所指向的位置的变量,也就是a,因此可以通过改变*x
的值来改变a的值,对于y来说也是如此。
运行结果应当为:
before a = 1 b = 2
after a = 2 b = 1
但这并不代表传递指针就可以改变变量的值。就拿上面的例子来说,传入的参数两个都是指针,假如函数中有一个命令x = y;,执行后将会使x的值为b的地址,也就是说,此时的x是指向b的指针。但是在这种情况下,显然a的值和a的地址都不会有任何改变,因此,在C中的所有参数传递方式都是值传递。
C++引用传递
void swap(int &x, int &y) //将a,b引用传递给函数
{
int temp;
temp = x;
x = y;
y = temp;
}
在C++中,还提供了一种特殊的参数引用方式,称之为引用传递,通过引用传递,可以在函数中改变参数原本的值。
使用swap(a, b);
调用该函数时,并没有产生新的临时变量,而是将参数本身传递给了函数,x和y可以理解为a和b的别名,它们共享同一个存储空间。也就是说,对于x和a来说,无论它们的值,还是他们的地址,都是相同的。在函数中改变x的值,实际上就是对a进行相同的操作,因此,a和b的值会被函数所改变。
运行结果应当为:
before a = 1 b = 2
after a = 2 b = 1
总结
对于C来说,函数引用参数的方法仅有值传递,无法改变传入变量的值。如果函数需要改变多个变量的值,则需要间接的值传递,及将变量的地址传递给函数,通过取址运算符*的作用来间接改变变量的值。
而对于C++来说,在C的基础上,还提供了引用传递,可以通过给变量赋予别名的方式,直接改变引用变量的值。
补充:
指针传递和引用传递辨析
int a = 1;
int *x = &a; //指针传递,x为指向a的指针
int &x = a; //引用传递,x为a的别名