我们知道,C语言中函数调用是以传值的方式将参数值传递给被调函数的,也就是说传递的是变量的值,而不是变量本身,因此被调函数不能修改主调函数中的变量的值。
但现在我们有了指针,这便不是个问题了。
第五章 指针与数组 >> 5.2 指针与函数参数
先来看一个排序时,交换两个元素顺序的例子:
void swap(int x, int y) /* Wrong!!! */ { int temp; temp = x; x = y; y = temp; }
以上是个错误的例子,调用 swap(a, b) 并不能达到我们想要的结果,因为这个 swap() 函数仅仅只是交换了 a 和 b 的副本的值,并没有将主调函数中的 a 和 b 的值调换。
解决办法是,将 a 和 b 的地址(也就是指针)作为参数传递给 swap 函数:
void swap(int *px, int *py) /* interchange *px and *py */ { int temp; temp = *px; *px = *py; *py = temp; }
调用 swap(&a, &b) 来实现 a 和 b 的值调换,因为通过指向 a 和指向 b 的指针,我们是间接地访问 a 和 b 的内存存储单元。通过下面这个图,可以看出实际变量与指针参数的关系:
指针参数使得被调函数能够访问和修改主调函数中对象的值。
再来看一个 getint 函数的例子。getint() 接受自由格式的输入,并执行转换,将输入的字符流分解成整数,且每次调用得到一个整数。而且 getint() 需要返回转换后得到的整数,且在到达输入结尾时要返回文件结束标记。
设计思路是:将标识是否到达文件结尾的状态作为 getint 函数的返回值,同时,利用一个指针参数存储转换后得到的整数,并传回给主调函数。
具体代码如下,这个版本的 getint 函数在到达文件结尾时返回EOF,当下一个输入不是数字时返回0,当输入中包含一个有意义的数字时返回一个正值:
#include <ctype.h> int getch(void); void ungetch(int); /* getint: get next integer from input into *pn */ int getint(int *pn) { int c, sign; while(isspace(c = getch())) /* skip white space */ ; if(!isdigit(c) && c != EOF && c != '+' && c != '-') { ungetch(c); /* it is not a number */ return 0; } sign = (c == '-') ? -1 : 1; if(c == '+' || c == '-') c = getch(); for(*pn = 0; isdigit(c); c = getch()) *pn = 10 * *pn + (c - '0'); *pn *= sign; if(c != EOF) ungetch(c); return c; }
*pn 始终作为一个普通的整型变量使用。其中还利用 getch 和 ungetch 函数,保证 getint 能确定读到的是一个完整整数且不影响下一次整数的读取。
这时,我们利用下面的循环语句调用 getint 函数,来给一个 int 类型 数组赋值:
int n, array[SIZE], getint(int *); for(n = 0; n < SIZE && getint(&array[n]) != EOF; n++) ;
这里必须将 array[n]的地址传递给函数 getint,否则 getint() 将无法把转换得到的整数传回给主调函数。