@
函数指针
定义
函数指针(也称为子例程指针或过程指针)是指向函数的指针。与引用数据不同, 函数指针指向内存中的可执行代码。解引用函数指针时, 就如同引用函数一样, 可以调用和传递参数。 这样的调用就称之为间接调用, 因为函数是通过变量间接调用的,而不是直接通过固定的标识符或地址调用。
声明
类型说明符 (*函数名) (参数)
比如
int (*p)(int x, int y);// 该函数指针对应的函数指针类型为 int (*) (int a, int b);
void (*foo)(int);
初始化
- 方式一:对应的函数名赋值给变量
- 方式二:函数名前加 & 符号再赋值给变量
其实两种方式是一样的。 就如同数组, 我们可以通过 &变量名 的方式取得数组的地址, 也可以通过直接 变量名 取得地址。
举例
double cm_to_inches(double cm)
{
return cm / 2.54;
}
double (*func1)(double) = cm_to_inches;
// 或 double (*func1)(double) = &cm_to_inches;
c 语言中的示例
#include <stdio.h> /* for printf */
#include <string.h> /* for strchr */
double cm_to_inches(double cm)
{
return cm / 2.54;
}
// "strchr" is part of the C string handling (i.e., no need for declaration)
// See https://en.wikipedia.org/wiki/C_string_handling#Functions
int main(void)
{
double (*func1)(double) = cm_to_inches;
char * (*func2)(const char *, int) = strchr;
printf("%f %s", func1(15.0), func2("Wikipedia", 'p'));
/* prints "5.905512 pedia" */
return 0;
}
结果
直接调用函数, 肯定是比使用函数指针方便, 容易。而函数指针在作为回调函数时可以让我们的编程变得更加简单。
#include <math.h>
#include <stdio.h>
// Function taking a function pointer as an argument
double compute_sum(double (*funcp)(double), double lo, double hi)
{
double sum = 0.0;
// Add values returned by the pointed-to function '*funcp'
int i;
for(i = 0; i <= 100; i++)
{
// Use the function pointer 'funcp' to invoke the function
double x = i / 100.0 * (hi - lo) + lo;
double y = funcp(x);
sum += y;
}
return sum / 101.0;
}
double square(double x)
{
return x * x;
}
int main(void)
{
double sum;
// Use standard library function 'sin()' as the pointed-to function
sum = compute_sum(sin, 0.0, 1.0);
printf("sum(sin): %g
", sum);
// Use standard library function 'cos()' as the pointed-to function
sum = compute_sum(cos, 0.0, 1.0);
printf("sum(cos): %g
", sum);
// Use user-defined function 'square()' as the pointed-to function
sum = compute_sum(square, 0.0, 1.0);
printf("sum(square): %g
", sum);
return 0;
}
结果
在以上的函数中, 使用函数指针在另一个函数(compute_sum
)中调用所传入的函数(如 sin, con, square)。在该过程中, compute_sum
函数通过funcp
所传入的函数, 实现compute_sum
函数达到不同的效果。
与typedef结合
在实际的使用过程中, 为了更易于阅读, 更多的会结合typedef
方式进行。
#include <stdio.h> /* for printf */
#include <string.h> /* for strchr */
typedef double(*Func1)(double);
typedef char* (*Func2)(const char *, int);
double cm_to_inches(double cm)
{
return cm / 2.54;
}
int main(void)
{
Func1 func1 = cm_to_inches;
Func2 func2 = strchr;
printf("%f %s", func1(15.0), func2("Wikipedia", 'p'));
/* prints "5.905512 pedia" */
return 0;
}
函数指针数组
其声明如下
类型说明符 (*函数名[数组长度]) (参数)
举个例子
#include <stdio.h> /* for printf */
char * fun1(char * p)
{
printf("%s
", p);
return p;
}
char * fun2(char * p)
{
printf("%s
", (p+1));
return p;
}
char * fun3(char * p)
{
printf("%s
", (p+2));
return p;
}
int main() {
char * (*pf[3])(char * p);
pf[0] = fun1;
pf[1] = &fun2;
pf[2] = &fun3;
pf[0]("fun1");
pf[1]("fun2");
pf[2]("fun3");
/**
* 输出:
* fun1
* un2
* n3
*/
return 0;
}
结果
或者使用函数指针声明成数组的形式。
#include <stdio.h> /* for printf */
typedef char * (*Func)(char * p);
char * funa1(char * p)
{
printf("%s
", p);
return p;
}
char * funa2(char * p)
{
printf("%s
", (p + 1));
return p;
}
char * funa3(char * p)
{
printf("%s
", (p + 2));
return p;
}
int main()
{
Func pf[3];
pf[0] = funa1;
pf[1] = funa2;
pf[2] = funa3;
pf[0]("Func0");
pf[1]("Func1");
pf[2]("Func2");
return 0;
}
结果如下
注意事项
- 赋给函数指针的函数应该和函数指针所指的函数原型(返回值, 参数一致)是一致的
- 函数指针没有 ++ 和 -- 操作