8-4. 指针作为参数传递

  • 学习人数 30K+
  • 适合所有人群学习
avatar
林耿亮

你好编程主讲老师

1. 探究实参与形参它们相互独立

还记得在函数那一节中讨论过的代码吗?

#include <stdio.h>
void swap(int x, int y)
{
    int temp = x;
    x = y;
    y = temp;
}

int main()
{
    int a, b;
    int temp;
    a = 1;
    b = 2;

    printf("a=%d b=%d\n", a, b);
    //  交换a,b变量
    swap(a, b);

    printf("a=%d b=%d\n", a, b);
    return 0;
}

由于主调函数的变量a,b与被调函数的形参x,y它们相互独立。函数swap可以修改变量x,y,但是却无法影响到主调函数中的a,b。

现在利用取地址运算符,分别打印它们的首地址,让我们从内存的角度,来分析一下它们。

#include <stdio.h>
void swap(int x, int y)
{
    //  打印x,y的首地址
    printf("&x= %u\n", &x);
    printf("&y= %u\n", &y);

    int temp = x;
    x = y;
    y = temp;
}

int main()
{
    int a, b;
    int temp;
    a = 1;
    b = 2;

    //  打印a,b的首地址
    printf("&a= %u\n", &a);
    printf("&b= %u\n", &b);

    //  交换a,b变量
    swap(a, b);

    return 0;
}

实参与形参首地址不同

a在内存中为首地址10484860开始的sizeof(int)字节。 b在内存中为首地址10484856开始的sizeof(int)字节。

x在内存中为首地址10484832开始的sizeof(int)字节。 y在内存中为首地址10484836开始的sizeof(int)字节。

主调函数内部的a、b地址

调用swap函数时,a的值1,传给x。b的值2,传给y。

被调函数内部x、y的值

图中,红色数值为数据对象首地址,黑框内的为变量名和值。 即使x,y已经交换了,但是并未影响a,b。

2. 将指针作为参数传递

由于在被调函数内部无法直接修改主调函数的变量。那么我们采用迂回战术,在函数main中取得a、b的指针。将两个指针传递到函数swap。那么,在函数swap内部可以根据这两个信息修改a、b。

这下,我们就需要用到指针类型作为参数了。

#include <stdio.h>
void swap(int *x, int *y)
{
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main()
{
    int a, b;
    int temp;
    a = 1;
    b = 2;

    printf("a=%d b=%d\n", a, b);
    //  交换a,b变量
    swap(&a, &b);

    printf("a=%d b=%d\n", a, b);
    return 0;
}

使用指针更改a、b

现在将xy改为了int *类型的指针。在主调函数中,对ab进行取地址获取指针并传入函数swap。在函数swap内部,通过这两个指针交换目标数据对象的值。注意,不是交换指针x,y的值,而是交换目标数据对象a,b的值。所以,需要在指针前使用取值运算符*

使用指针交换实参

图中,红色数值为数据对象首地址,黑框内的为变量名和值。

现在终于能解释为何在使用scanf函数时,需要对变量先取地址再传入参数了。

int n;
scanf("%d", &n);

scanf会从读取从键盘的输入,转换后存储到变量n当中。被调函数scanf无法直接修改在主调函数中的变量n。因此,我们将变量n的指针传入scanf函数。通过指针使得被调函数间接地修改主调函数中的变量。