2.4 作为函数参数的指针

来源:互联网 发布:网络舆情监测员职责 编辑:程序博客网 时间:2024/04/27 02:43

2.4 作为函数参数的指针

在C语言的函数调用中指针起着至关重要的作用。最重要的是指针支持将参数作为引用传递给函数。参数作为引用传递时,当函数改变此参数,那么这个被改变参数的值会一直存在,甚至函数退出后都仍然存在。相对而言,参数作为值传递时,此时值的改变只能持续到函数返回时。无论是否要改变函数的输入输出参数,我们用传引用的方式来传递大容量复杂的函数参数都是十分高效手段。这种方法高效的原因就在于,我们只是传递一个指针而不是一个数据的完整拷贝到函数中去,这样可以大大的节省内存空间。本书中多处都用到了这种方法。

2.4.1 按引用传递参数

在形式上,C语言只支持按值来传递参数。在按值传递的过程中,函数参数的一份私有拷贝将会被用到函数的执行体中。然而,我们可以模仿传值的方式将一个指向参数的指针(而不是参数本身)传递给函数,这样函数调用者就可以得到一个指针的副本用于函数体的执行过程。

要了解传引用是如何现实的,我们来看看swap1swap1是一个实现将两个整型变量相互交换的函数,函数参数是通过值传递的,所以得到的结果是错误的。图2.4说明了为什么交换函数不起作用。swap2同样是一个交换函数,只是它的参数是按引用传递的。图2.5说明如何使用指针来修正swap1错误。

Incorrect Swap

Correct Swap

void swap1(int x, int y)

    int tmp;

    tmp = x; x = y; y = tmp; 

    return; 

}

void swap2(int *x, int *y)

    int tmp;

    tmp = *x; *x = *y; *y = tmp; 

    return; 

}

图2.4 按传值方式传参数的swap1函数的运行过程

图2.5 按传引用方式传参数的swap2函数的运行过

关于C语言中按引用传递参数,其好的一面是语言本身赋予了我们精确控制参数传递的能力。不好的方面是,这种控制有时候会显得很麻烦,因为我们常常需要在函数中多次对参数进行解引用操作。

另一个在函数调用时会用到指针的地方,就是把数组传递给函数的时候。回顾之前我们所说的,C语言把数组名当作一个不可变的指针来使用,当向函数传递一个类型为T的数组对象时,其实就等同于向函数传递一个指向类型为T的对象的指针。所以,我们可以交替使用这两种方法。例如:函数f1和函数f2是功能是一样的。

Array Reference

Pointer Reference

int f1(int a[])

    a[0] = 5; 

    return 0; 

}

int f2(int *a)

    *a = 5; 

    return 0; 

}

具体使用哪种方式来传递参数取决于约定俗成习惯或函数处理参数的方法。当使用一个数组做为参数时,数组的边界信息并不重要,因为此时编译器并不要求数组有边界信息。但是,提供边界信息对于表达出函数内部处理该参数具有一定的局限性时是一种很有用的方法。在使用多维数组做参数的函数中,边界信息显得尤为重要。

当把一个多维数组传递给函数时,除了第一维以外,其他维的长度必须指定,这样函数才能通过指针算术运算访问到具体元素。如以下代码如示:

int g(int a[][2]) {    a[2][0] = 5;    return 0;}


为了更清楚的理解为什么我们必须指定第一个维度的大小,我们设定有一个3行2列整型二维数组。在C语言中,此二维数组的元素在内存中按照地址的递增一行一行顺序排列。就是说,第1行的两个整数存储在前两个位置,接着是第2行的两个整数,再接着是第3行的两个整数。所以,如果想访问到任一行的元素(除了第1行)时,我们首先必须知道达到这一行我们需要跳过多少个连续的元素(见图2.6)

图2.6 在2*3的数组的第3行第0行放一个整数5(图a),图b是内存中的图示

2.4.2 作为参数的指向指针的指针

在本书有很多把指针当作参数传递给函数的地方,这是由于函数想改变传递给它的指针。想做到这一点,函数就会被传进来一个想要被改变的指向指针的指针。来看一下在第5章定义的一个函数list_rem_next,这个函数的功能就是从链表的删除一个元素。当此函数返回时,data指向了被删除的元素:

int list_rem_next(List *list, ListElmt *element, void **data);


由于此函数需要改变data使data指向被删除的那个元素的数据,所以我们必须将指针data的地址传递给函数以模仿传引用的方式来传递参数(见图2.7),所以,函数传入一个指向指针的指针作为它的第三个参数。在本书中,这是一个典型的用来删除数据结构中数据的方法。

图2.7 函数改变指向指针的指针的过程

 

PS:

1、此书(Mastering Algorithms with C)译稿版权归本人(Love_Lei)及好友(bigship)共同所有,未经本人同意谢绝一切转载,并不得抄袭,模仿,盗版!更请大家监督盗版之人!

2、由于本人水平有限,如对译文有任何建议和异议,欢迎大家留言指正,我们共同讨论学习!谢谢!