原创文章,转载请注明: 转载自工学1号馆
函数指针是一种在C、C++、D语言、其他类 C 语言和Fortran 2003中的指针。函数指针可以像一般函数一样,用于调用函数、传递参数。在如 C 这样的语言中,通过提供一个简单的选取、执行函数的方法,函数指针可以简化代码。
函数指针只能指向具有特定特征的函数。因而所有被同一指针运用的函数必须具有相同的参数和返回类型。
下面的代码说明了一种初始化函数指针的方法:
int f(int); int (*fp)(int) = &f; //使用三种方式调用函数 int ans; ans = f(25); ans = (*pf)(25); ans = pf(25);
以下为函数指针在C中的简单运用:
#include <stdio.h> int max(int x, int y) { return x > y ? x : y; } int main(void) { /* p 是函数指针 */ int (*p)(int, int) = &max; // &可以省略 int a, b, c, d; printf("please input 3 numbers:"); scanf("%d %d %d", &a, &b, &c); /* 与直接调用函数等价,d = max(max(a, b), c) */ d = (*p)((*p)(a, b), c); printf("the maxumum number is: %d\n", d); return 0; }
下面介绍函数指针最常见的两个用途:作为参数传递给另一个函数(回调函数)、转换表
1、回调函数:
下面有一个简单的函数,用来在单链表中查找一个给定的值
Node* search_list(Node* node, int const value) { while(node != NULL) { if(node->value == value) break; node = node->next; } return node; }
一种更加通用的方法就是使该函数能用任何类型值的链表,必须修改函数,使它与类型无关。解决的方案就是使用函数指针。
#include <stdio.h> #include "node.h" Node *search_list( Node *node, void const *value, int (*compare)( void const *, void const * ) ) { while( node != NULL ){ if( compare( &node->value, value ) == 0 ) break; node = node->next; } return node; }
在特定的链表中进行比较的时候,用户需要编写适当的比较函数,并把指向该函数的指针和指向需要查找的值的指针传递给查找函数,下面是一个整型链表中查找的比较函数:
int compare_ints(void const *a, void const *b) { if( *(int *)a == *(int *)b) return 0; else return 1; } //这个函数将像下面这样调用 desired_node = search_list(root, &desired_value, compare_ints);
如果你希望在一个字符串链表中进行查找,下面的代码可以完成任务:
#include<string.h> ... desired_node = search_list(root, "desired_value", strcmp);
再看一个完整的例子:
#include<stdio.h> struct object { int data; }; int object_compare(struct object * a,struct object * z) { return a->data < z->data ? 1 : 0; } struct object *maximum(struct object * begin,struct object * end,int (* compare)(struct object *, struct object *)) { struct object * result = begin; while(begin != end) { if(compare(result, begin)) { result = begin; } ++ begin; } return result; } int main(void) { struct object data[8] = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}}; struct object * max; max = maximum(data + 0, data + 8, & object_compare); printf("max: %d\n", (*max).data); return 0; }
2、转移表
下面的程序是一个简化的根据运算符转到相应运算的例子:
#include<stdio.h> double _add(double, double); double _sub(double, double); double _mul(double, double); double _div(double, double); double _add(double a, double b) { return a + b; } double _sub(double a, double b) { return a - b; } double _mul(double a, double b) { return a * b; } double _div(double a, double b) { return a / b; } int main(void) { int n; enum Operation{ADD, SUB, MUL, DIV}op; double a, b, ans; a = 0.232332; b = 0.234398; printf("请输入一个整数(0-3): "); scanf("%d", &n); op = (enum Operation)n; switch(op) { case ADD: ans = _add(a, b); break; case SUB: ans = _sub(a, b); break; case MUL: ans = _mul(a, b); break; case DIV: ans = _div(a, b); break; default: break; } printf("%lf\n", ans); return 0; }
使用可以使用转换表来实现相同的任务,转换表就是一个函数指针数组,代码如下:
#include<stdio.h> double _add(double, double); double _sub(double, double); double _mul(double, double); double _div(double, double); double _add(double a, double b) { return a + b; } double _sub(double a, double b) { return a - b; } double _mul(double a, double b) { return a * b; } double _div(double a, double b) { return a / b; } int main(void) { int n; double a, b, ans; a = 0.232332; b = 0.234398; printf("请输入一个整数(0-3): "); scanf("%d", &n); double (*oper_func[])(double, double) = { _add, _sub, _mul, _div }; ans = oper_func[n](a, b); printf("%lf\n", ans); return 0; }
Comments