您不会每天都使用函数指针,但是,他们确有用武之地,两个最常见的用途是把函数指针作为参数传递给另一个函数连同用于转换表(jump table)

【警告】简单声明一个函数指针并不意味着他马上就能够使用。和其他指针相同,对函数指针执行间接访问之前必须把他初始化为指向某个函数。下面的代码段说明了一种初始化函数指针的方法。
int f(int);
int (*pf)(int)=&f;
第 2 个声明创建了函数指针 pf ,并把他初始化为指向函数 f 。 函数指针的初始化也能够通过一条赋值语句来完成。 在函数指针的初
始化之前具备 f 的原型是很重要的,否则编译器就无法检查 f 的类型是否和 pf 所指向的类型一致。

初始化表达式中的 & 操作符是可选的,因为函数名被使用时总是由编译器把他转换为函数指针。 & 操作符只是显式地说明了编译器隐式执行的任务。

在函数指针被声明并且初始化之后,我们就能够使用三种方式调用函数:
int ans;

ans=f(25);
ans=(*pf)(25);
ans=pf(25);
第 1 条语句简单地使用名字调用函数 f ,但他的执行过程可能和您想象的不太相同。 函数名 f 首先被转换为一个函数指针,该指针指

定函数在内存中的位置。然后, 函数调用操作符调用该函数,执行开始于这个地址的代码。
第 2 条语句对 pf 执行间接访问操作,他把函数指针转换为一个函数名。这个转换并不是真正需要的,因为编译器在执行函数调用操作符

之前又会把他转换回去。但是,这条语句的效果和第1条是完全相同的。
第 3 条语句和前两条的效果是相同的。间接访问并非必需,因为编译器需要的是个函数指针。

(一)回调函数
这里有一个简单的函数,他用于在单链表中查找一个值。他的参数是个指向链表第 1 个节点的指针连同那个需要查找的值。
Node *
search_list(Node *node, int const value)
{
while(node!=NULL){
if( node->value == value )
break;
node = node->link;
}
return node;
}

这个函数看上去相当简单,但他只适用于值为整数的链表。假如您需要在一个字符串链表中查找,您不得不另外编写一个函数。这个函数和上面那个函数的绝大部分代码相同,只是第 2 个参数的类型连同节点值的比较方法不同。

一种更为通用的方法是使查找函数和类型无关,这样他就能用于任何类型的值的链表。我们必须对函数的两个方面进行修改,使他和类型无关。

首先,我们必须改变比较的执行方式,这样函数就能够对任何类型的值进行比较。这个目标听上去似乎不可能,假如您编写语句用于比较整型值,他怎么还可能用于其他类型如字符串的比较呢? 解决方案就是使用函数指针。 调用者编写一个比较函数,用于比较两个值,然后把一个指向此函数的指针作为参数传递给查找函数。 而后查找函数来执行比较。使用这种方法,任何类型的值都能够进行比较。

我们必须修改的第 2 个方面是向比较函数传递一个指向值的指针而不是值本身。比较函数有一个 void * 形参,用于接收这个参数。然后指向这个值的指针便传递给比较函数。(这个修改使字符串和数组对象也能够被使用。字符串和数组无法作为参数传递给函数,但指向他们的指针却能够。)

使用这种技巧的函数被称为回调函数(callback function),因为用户把一个函数指针作为参数传递其他函数,后者将”回调“用户的函数。任何时候,假如您所编写的函数必须能够在不同的时刻执行不同类型的工作或执行只能由函数调用者定义的工作,您都能够使用这个技巧。

【提示】
在使用比较函数的指针之前,他们必须被强制转换为正确的类型。因为强制类型转换能够躲开一般的类型检查,所以您在使用时必须格外小心,确保函数参数类型是正确的。

在这个例子里,回调函数比较两个值。查找函数向比较函数传递两个指向需要进行比较的值的指针,并检查比较函数的返回值。例如:零表示相等的值,现在查找函数就和类型无关,因为他本身并不执行实际的比较。确实,调用者必须编写必需的比较函数,但这样做是很容易的,因为调用者知道链表中所包含的值的类型。 假如使用几个分别包含不同类型值的链表,为每种类型编写一个比较函数就允许单个查找函数作用于任何类型的链表。

程式段01 是类型无关的查找函数的一种实现方法。 注意函数的第 3 个参数是个函数指针。这个参数用一个完整的原型进行声明。同时注意虽然函数绝不会修改参数 node 所指向的任何节点,但 node 并未被声明为 const 。假如 node 被声明为 const, 函数将不得不返回一个const结果,这将限制调用程式,他便无法修改查找函数所找到的节点。
/*
**程式 01 ——类型无关的链表查找函数
**在一个单链表中查找一个指定值的函数。他的参数是个指向链表第 1 个节点的指针、一个指向我们需要 查找的值的指针和一个函数指针。
**他所指向的函数用于比较存储于链表中的类型的值。
*/
#include <stdio.h>
#include "node.h"

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!