函数参数用于向函数传递数据,C语言支持两种传递方式:值传递和引用传递。
一,值传递
传递参数的副本,函数内对参数的修改不影响原变量。
void swapByValue(int x, int y) {
int temp = x;
x = y;
y = temp; // 交换操作仅影响局部副本
}
int main() {
int a = 5, b = 10;
swapByValue(a, b);
printf("a = %d, b = %d\n", a, b); // 输出不变:a = 5, b = 10
}
上述代码,通过值传递调用函数swapByValue(int x, int y)
,表面上起到了交换a和b的值的作用,实则并未改变a和b的值。
这是因为调用函数时是将a
和b
的值复制一份后,赋值给形参变量x
和y
,之后对x
和y
的操作不会影响a
和b
的值。
二,引用传递
传递参数的地址,通过指针实现,函数内可通过地址修改原变量。
void swapByReference(int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp; // 实际交换变量的值
}
int main() {
int a = 5, b = 10;
swapByReference(&a, &b);
printf("a = %d, b = %d\n", a, b); // 输出交换后:a = 10, b = 5
}
上述代码,通过值传递调用函数swapByValue(int* x, int* y)
,表面上起到了交换a和b的值的作用,实际上的确起到了这个作用。
这是因为调用函数时是将a
和b
的地址传递给了指针变量x
和y
,函数体内通过运算符*
对x
和y
进行运算,本质上操作x
和y
指向的内存中的数据,也即是变量a
和b
的数据。
三,从内存原理看值传递和引用传递的区别
C代码在执行时,以函数为单位创建栈帧,栈帧中为变量分配内存空间,值传递和引用传递的根本区别在于变量的内存空间存储的数据不同。
1 值传递内存示意图
void swapByValue(int x, int y) {
int temp = x;
x = y;
y = temp; // 交换操作仅影响局部副本
}
int main() {
int a = 5, b = 10;
swapByValue(a, b);
printf("a = %d, b = %d\n", a, b); // 输出不变:a = 5, b = 10
}
对于上述值传递代码,如下图所示,main
函数调用swapByValue
函数,采用值传递,相当于把main
栈帧变量a
和b
的内存中的值copy到swapByValue
栈帧中变量x
和y
的内存区域,之后swapByValue
函数中操作x
和y
的内存中存储的值,并不会影响main
栈帧中变量a
和b
的内存中的值。
2 引用传递内存示意图
void swapByReference(int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp; // 实际交换变量的值
}
int main() {
int a = 5, b = 10;
swapByReference(&a, &b);
printf("a = %d, b = %d\n", a, b); // 输出交换后:a = 10, b = 5
}
对于如上引用传递代码,如下图所示,传递给swapByValue
栈帧中变量x
和y
的值是main
栈帧中变量a
和b
的地址,swapByValue
函数中通过星号运算符*
结合x
和y
中存储的地址值,找到main
栈帧中变量a
和b
,并对其进行读写,所以main
栈帧中变量a
和b
的值会交换。