函数指针概念
函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。
以上的概念是参考百度词条来的,简单的讲就是指向函数的指针。
用途
通过以上的概念可以明确,指针函数的用途是调用函数和做函数的参数。
Talk is cheap. Show me the code.从这两个用途举例说明:
调用函数
首先看到以下例子,利用函数指针实现一个简单的调度:
#include <stdio.h>
#define TASK_NUM sizeof(scheduler)/sizeof(struct task_schedule)
struct task_schedule
{
int num;
int (*func)(int);
};
int task1(int num)
{
printf("%s: %d!\n", __func__, num);
return 0;
}
int task2(int num)
{
printf("%s: %d!\n", __func__, num);
return 0;
}
int main()
{
int i = 0;
struct task_schedule scheduler[] = {
{0, task1},
{1, task2},
};
for(i = 0; i < TASK_NUM; i++){
scheduler[i].func(1);
printf("\n");
}
return 0;
}
以上例子的功能是遍历执行数组scheduler中所有的func函数,数组schedule是一个struct task_schedule类型的结构体, task_schedule结构体中func的定义就是运用了函数指针。在代码中将schedule的func成员指向实例的task1,task2函数入口,直接遍历即可执行task1,task2函数。
运行结果:
做函数参数
这里是将2.1代码中数组的赋值重新封装了一个接口:
#include <stdio.h>
typedef int (*PTASK)(int);
#define TASK_NUM sizeof(scheduler_list)/sizeof(struct task_schedule)
int task1(int num)
{
printf("%s: %d!\n", __func__, num);
return 0;
}
int task2(int num)
{
printf("%s: %d!\n", __func__, num);
return 0;
}
struct task_schedule
{
int num;
PTASK func;
//int (*func)(int);
};
void scheduler(struct task_schedule *sheduler, PTASK *task, int len)
{
int j = 0;
struct task_schedule *p;
p = sheduler;
for(; j < len; j++) {
p->num = j;
p->func = task[j];
p++;
}
}
int main()
{
int i = 0;
struct task_schedule scheduler_list[2];
PTASK task_all[] = {task1, task2};
scheduler(scheduler_list, task_all, 2);
for(i = 0; i < TASK_NUM; i++){
scheduler_list[i].func(1);
printf("\n");
}
return 0;
}
scheduler(struct task_schedule *sheduler,PTASK *task, int len)函数就是将PTASK函数指针作为参数,从而在此函数中填充sheduler数组,然后遍历。当函数指针作为参数时,这里用了typedef将函数指针重新声明,通过比较前后代码可以看出区别。下次也会讲一下typedef与函数指针搭配使用的原理。
输出结果: