5.2 指针与函数参数
由于 C 语言是以传值的方式将参数值传递给被调用函数的
因此,被调用函数不能直接修改主调函数中变量的值
例如,排序函数可能会使用一个名为 swap
的函数来交换两个次序颠倒的元素
但是,如果将 swap
函数定义为下列形式:
void swap(int x, int y) /* WRONG */
{
int temp;
temp = x;
x = y;
y = temp;
}
则 swap(a, b);
无法达到该目的
由于参数传递采用传值方式,因此上述的 swap
函数不会影响到调用它的例程中的参数 a
和 b
的值
该函数仅仅交换了 a
和 b
的副本的值
为了实现目标,可以使主调程序将指向所要交换的变量的指针传递给被调用函数:swap(&a, &b);
由于一元运算符 &
用来取变量的地址,这样 &a
就是一个指向变量 a
的指针
swap
函数的所有参数都声明为指针,并且通过这些指针来间接访问它们指向的操作数
void swap(int *px, int *py) /* interchange *px and *py */
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
指针参数使得被调用函数能够访问和修改主调函数中对象的值
例子:
函数 getint
接受自由格式的输入,并执行转换,将输入的字符流分解成整数,且每次调用得到一个整数
getint
需要返回转换后得到的整数,并且,在到达输入结尾时要返回文件结束标记,这些值必须通过不同的方式返回
EOF
(文件结束标记)可以用任何值表示,当然也可用一个输入的整数表示
可以这样设计该函数:
将标识是否到达文件结尾的状态作为 getint
函数的返回值
同时,使用一个指针参数存储转换后得到的整数并传回给主调函数
函数 scanf
的实现就采用了这种方法,具体细节请参见 7.4 节
下面的循环语句调用 getint
函数给一个整型数组赋值:
int n, array[SIZE], getint(int *);
for (n = 0; n < SIZE && getint(&array[n]) != EOF; n++)
每次调用 getint
时,输入流中的下一个整数将被赋值给数组元素 array[n]
,同时,n
的值将增加 1
请注意,这里必须将 array[n]
的地址传递给函数 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;
}
在 getint
函数中,*pn
始终作为一个普通的整型变量使用
其中还使用了 getch
和 ungetch
两个函数(参见 4.3 节)
借助这两个函数,函数 getint
必须读入的一个多余字符就可以重新写回到输入中