文章目录
- 一,值传递
- 二,引用传递
- 三,从内存原理看值传递和引用传递的区别
- 1 值传递内存示意图
- 2 引用传递内存示意图
- 参考文献
函数参数用于向函数传递数据,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
的值会交换。
参考文献
1,https://blog.csdn.net/qq_40507857/article/details/114966115?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171918705616800222879077%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=171918705616800222879077&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogbaidu_landing_v2~default-3-114966115-null-null.nonecase&utm_term=%E5%80%BC%E4%BC%A0%E9%80%92%E5%92%8C%E5%BC%95%E7%94%A8%E4%BC%A0%E9%80%92c&spm=1018.2226.3001.4450