Cprogramming 简明教程
Function Call by Reference in C
函数可以通过两种方式调用:(a)按值调用和 (b) 按引用调用。在本章中,我们将解释按引用调用函数的机制。
让我们从简要概述“指针”和“地址运算符 (&)”开始本章。为了完全理解按引用调用的机制,学习这两个概念非常重要。
The Address Operator (&) in C
在 C 语言中,变量是一个已命名的内存位置。当声明变量时,编译器将在内存中分配一个随机位置,并在内部使用用户定义的名称标识该位置。
要获取创建变量的地址,我们使用 address (&) operator 。
What is a Pointer in C?
指针是一个存储另一个变量地址的变量。要声明一个指针变量,它的名称前面加上 * 符号。指针变量的类型及其宿主变量的类型必须相同。
地址分配给 & 运算符。 dereference operator ( )* 与指针一起使用。它获取地址分配给指针的变量的值。
Example
以下示例演示了如何在 C 中进行引用和解引用 −
#include <stdio.h>
int main(){
int x = 10;
int *y = &x;
printf("x: %d Address of x: %d\n", x, &x);
printf("Address of y: %d \n", &y);
printf("Value at address in y: %d\n", *y);
}
运行代码并检查其输出:
x: 10 Address of x: -1742755108
Address of y: -1742755104
Value at address in y: 10
How Does Call by Reference Work in C?
当按引用调用函数时,将传递实际参数变量的地址,而不是它们的值。
让我们定义一个接收两个变量的引用作为参数的 add()
函数 −
int add(int *x, int *y){
int z = *x + *y;
return z;
}
当调用此函数时,会传递实际参数的地址。
Example
让我们从 main()
函数的内部通过引用调用 add()
函数 −
#include <stdio.h>
/* function declaration */
int add(int *, int *);
int main(){
int a = 10, b = 20;
int c = add(&a, &b);
printf("Addition: %d", c);
}
int add(int *x, int *y){
int z = *x + *y;
return z;
}
当你运行这段代码时,它将产生以下输出:
Addition: 30
现在让我们了解此代码的实际工作原理。 main()
函数将 @s0
和 @s1
的地址传递给 @s2
函数。 @s3
和 @s4
的地址被分配给指针变量 @s5
和 @s6
。
现在关注语句 "z = @s7" 存储 @s8
的地址。 @s9
和 @s10
中的解引用运算符分别获取 @s11
和 @s12
的值,因此 @s13
是 main()
函数中 @s14
和 @s15
的和。
Example: Swap Values with Call by Reference
让我们在以下交换两个变量值的示例的帮助下,更详细地了解按引用调用机制如何工作。
#include <stdio.h>
/* Function definition to swap the values */
/* It receives the reference of two variables whose values are to be swapped */
int swap(int *x, int *y){
int z;
z = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = z; /* put z into y */
return 0;
}
/* The main() function has two variables "a" and "b" */
/* Their addresses are passed as arguments to the swap() function. */
int main(){
/* local variable definition */
int a = 10;
int b = 20;
printf("Before swap, value of a: %d\n", a );
printf("Before swap, value of b: %d\n", b );
/* calling a function to swap the values */
swap(&a, &b);
printf("After swap, value of a: %d\n", a);
printf("After swap, value of b: %d\n", b);
return 0;
}
当你运行这段代码时,它将产生以下输出:
Before swap, value of a: 10
Before swap, value of b: 20
After swap, value of a: 20
After swap, value of b: 10
Explanation
假设 main()
函数中的变量 @s16
和 @s17
被分配了内存地址为 100 和 200 的位置。当它们的地址传递给 @s18
和 @s19
(请记住,它们是指针)时,swap() 函数中的变量 @s20
、 @s21
和 @s22
分别被创建于地址 1000、2000 和 3000。
由于 "x" 和 "y" 存储 "a" 和 "b" 的地址,正如上图所示,因此 "x" 变为 100,而 "y" 变为 200。
在 swap()
函数内部,第一条语句 @s23
使地址存储在 "x" 中的值存储在 "x" 中(值为 10)。类似地,在语句 @s24
中,地址存储在 "y" 中的值(值为 20)存储在其指针为 "x" 的位置。
最后,语句 @s25
将 "z" 分配给由 "y" 指向的变量,即 main()
函数中的 "b"。现在 "a" 和 "b" 的值发生了交换。
下图直观地展示了其工作原理 −
Mixing Call by Value and Call by Reference
你可以使用按值调用和按引用调用相结合的函数调用机制。它可以被称为“混合调用机制”,其中一些参数按值传递,而另一些参数按引用传递。
C 中的函数可以有多个参数,但只能返回一个值。按引用调用机制是克服此限制的一个很好的解决方案。
Example
在这个示例中, calculate()
函数通过值接收一个整型参数,通过两个指针存储其平方和立方。
#include <stdio.h>
#include <math.h>
/* function declaration */
int calculate(int, int *, int *);
int main(){
int a = 10;
int b, c;
calculate(a, &b, &c);
printf("a: %d \nSquare of a: %d \nCube of a: %d", a, b, c);
}
int calculate(int x, int *y, int *z){
*y = pow(x,2);
*z = pow(x, 3);
return 0;
}
当你运行这段代码时,它将产生以下输出:
a: 10
Square of a: 100
Cube of a: 1000
当函数需要执行内存级别的操作(例如控制外围设备、执行动态分配等)时,按引用调用机制被广泛使用。