函数指针之回调函数和转移表
《C和指针》261页
函数指针的用途:
- 对不同的数据类型作相同的操作->回调函数
- 对相同的数据类型作不同的操作->转移表
函数指针的声明:
1. int (*f)( int, float ); //f是一个函数指针,函数的返回值为int,函数的参数分别是int和float
2. int *(*f)(); //f是一个函数指针,函数的返回值为int *
3. int (*f[])(); //f是一个元素类型为函数指针的数组,函数的返回值为int
4. int *(*f[])( int, float ); //f是一个元素类型为函数指针的数组,函数的返回值为int *,函数的参数分别是int和float
回调函数
概念
函数A调用函数B时,B的其中一个形参是函数指针pf,B在运行时调用A传过来的存在pf中的函数指针所指向的函数.pf所指向的函数被称为回调函数.
用途
为了函数A能够在不同的时刻执行不同类型的工作或者执行只能由函数调用者定义的工作.
举例: 使用回调函数提供通用函数
在一个单链表中查找一个值
Node *search_list( Node *node, int const value){...}
如何将上面的函数改成通用的函数,即不管链表中保存的值是什么类型都可以比较?
Node *search_list( Node *node, void const *value, int (*compare)( void const *, void const * ) ){...}//函数声明, compare所指向的函数就是回调函数
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 );
转移表
用途
把具体操作和选择操作的代码分开,避免出现长长的switch...case..
语句.
举例:
//常规写法
switch ( oper ){
case ADD:
result = add( oper1, oper2 );
break;
case SUB:
result = sub( oper1, oper2 );
break;
case MUL:
result = mul( oper1, oper2 );
break;
case DIV:
result = div( oper1, oper2 );
break;
...
}
//使用转移表之后的写法
double add( double, double );
double sub( double, double );
double mul( double, double );
double div( double, double );
...
double (*oper_func[])( double, double ) = {
add, sub, mul, div, ...
};
//下面的语句替换前面整条switch语句
result = oper_func[ oper ]( op1, op2 );