值传递与引用传递


2021年8月23日, Learn eTutorial
4123

在本教程中,您将学习函数参数传递的两种不同方法(传值调用和传引用调用)的所有知识,以及它们如何有用和不同。

函数参数

C 语言中的函数参数是在调用函数时使用的一组变量。通常,参数获取输入值并将其传递给函数定义中的相应形参。通常有两种方法可以将参数传递到函数中:

  • 传值调用
  • 传引用调用

在了解这两种方法之前,让我们先熟悉一下在传递参数时使用的另外两个重要术语:

  • 实际参数 - 函数调用中使用的参数
  • 形式参数 - 函数定义中使用的参数。

形式参数在定义函数时使用。而实际参数在函数调用执行时发挥作用。因此,形式参数设定规则,实际参数将其值代入以产生结果。为了更清楚地说明,请看下面的可视化。

Function call in C

C 语言中的函数调用

C 中的传值调用是什么

传值调用是一种在编程语言中用于将实际参数传递给形式参数的参数传递方法。顾名思义,这里传递的是参数的值。具体来说,在传递时,实际参数的值会被复制到形式参数。因此,在函数定义中对形式参数进行的任何更改或调整都不会影响函数调用中的实际参数。这是因为为实际参数和形式参数创建了两个独立的内存,很明显,我们正在处理两个不同的存储位置。

考虑以下程序


#include <stdio.h>
int tot( int a, int b)
{
     int c;
      c=a+b;
     printf("Before modification in function definition: a = %d and b = %d  \n",a,b);
     printf("Before modification in function definition : Total of a and b  - is :%d\n\n",c);

     a = a + 5;
     b = b + 5;
     c = a+b;
     printf("After modification in function definition: a = %d and b = %d  \n",a,b);
     printf("After modification in function definition : Total of a and b  - is :%d\n\n",c);

     return 0;
}

int main()
{
    int p =10;
    int q= 20;
    printf("Before function call in main():p = %d and q = %d  \n\n",p,q);
    int z = tot(p, q);
    printf("After function call in main():p = %d and q = %d  \n",p,q);
    return 0;
}

在此程序中,

  1. ab 是形式参数,它们的作用是定义公式,即 a+b=c
  2. 另一方面,pq 将被视为实际参数。它们的作用是将值 10 和 20 传递给形式参数。

输出将如下所示:


Before function call in main():p = 10 and q = 20

Before modification in function definition: a = 10 and b = 20
Before modification in function definition : Total of a and b  - is :30

After modification in function definition: a = 15 and b = 25
After modification in function definition : Total of a and b  - is :40

After function call in main():p = 10 and q = 20

当我们观察输出时,可以清楚地看到,在使用传值调用传递参数时,形式参数的值是可变的,而实际参数是不可变的。

C 中的传引用调用是什么

传引用调用是 C 语言中用于将参数传递到函数定义中的参数传递的另一种方法。在此函数调用过程中,将实际参数的地址传递到形式参数而不是值。这意味着实际参数和形式参数都使用相同的内存位置,因此对形式参数的任何更改都会立即反映在实际参数中。

要理解这一点,我们必须熟悉可以存储另一个变量地址的指针变量。假设

int i=10;
int *p; 
p=&i; 
 

Call by Reference

我们可以看到指针变量与 '*' 相关联。这里 p 是一个指针变量,它存储了 'i' 所在的地址。下面是演示传引用调用或地址使用的交换程序。


#include <stdio.h>

void swap_add(int * i, int * j);
void main(void) {
    int p = 5, q = 10;
    printf("\n In main() before swapping: p=%d, q=%d", p, q);
    swap_add( & p, & q);
    printf("\n In main () after swapping: p=%d q=%d", p, q);
}
void swap_add(int * i, int * j) {
    int temp;
    temp = * i;
    * i = * j;
    * j = temp;
    printf("\n Inside function definition after swapping:i=%d, j=%d", * i, * j);
}
 

在上述程序中,*i 和 *j 分别操作 p 和 q 地址中存储的值。因此,地址的交换导致了实际值的交换。所以程序的输出将是


In main() before swapping: p=5, q=10
Inside function definition after swapping:i=10, j=5
In main () after swapping: p=10 q=5

传值调用与传引用调用的区别。

序号 传值调用 传引用调用
1 重视值 重视地址
2 将值的副本传递给函数 将地址传递给函数
3 形式参数和实际参数使用不同的内存 形式参数和实际参数指向同一内存
4 在函数中对值的更改不会反映在主函数中 在函数中对值的更改会反映在主函数中