函数指针
1.前言
函数类型
函数有自己的特定类型,且由
返回值
、参数类型
、参数个数
共同决定(隐含了参数顺序)例如:
int add(int i, int j)
的类型为int(int, int)
通过typedef为函数重命名
typedef type name(parameter list)
例如:
typedef int f(int, int)
、type void p(int)
解释:定义函数f,返回值为int类型,参数有两个都为int类型,
1.函数指针
说明:
- 函数指针用于指向一个函数
- 函数名是指向执行函数体的入口地址
- 可以通过函数类型定义函数指针:
Func Type* pointer;
- 也可以直接定义:
type (*pointer) (parameter list);
pointer
为函数指针变量名type
为指向函数的返回值类型parameter list
为指向函数的参数类型列表
示例:
typedef int(FUNC)(int); //定义返回值为int,参数为一个int类型的函数类型 int test(int i) { return i * i; } void f() { printf("Call f()......\n"); } int main() { FUNC *pt = test; //定义一个函数指针pt存放test函数的地址 void(*pf)() = &f; //直接定义函数指针pf存放f函数的地址(为了兼容以前的编译器版本) pf(); //调用函数 (*pf)(); //调用函数 printf("Call : %d\n", pt(2)); return 0; }
2.回调函数
机制原理:
- 调用者不知道具体事件发生的时候需要调用的具体函数
- 被调函数不知道何时被调用,只知道被调用后要完成的任务
- 当具体事件发生时,调用者通过函数指针调用具体函数
示例:
typedef int(*FUNCTION)(int); //定能一个返回值为int,有一个参数为int类型的函数指针类型 int g(int n, FUNCTION f) { /*传递参数为FUNCTION类型的f (不知道将会用到什么类型)*/ int i = 0; int ret = 0; for(i = 0; i < n; ++i) { /*在遇到具体情况时调用具体的函数*/ ret += i * f(i); } return ret; } int f1(int x) { return x + 1; } int f2(int x) { return 2 * x - 1; } int f3(int x) { return -x; } int main() { /*调用g函数,遇到三种不同的情况,分别处理*/ printf("x * f1(x): %d\n", g(3, f1)); printf("x * f2(x): %d\n", g(3, f2)); printf("x * f3(x): %d\n", g(3, f3)); return 0; }
- 注:在处理程序时,可以进行模块化,使两个模块间不相互依赖
3.指针阅读技巧
左右法则:
- 从最里层(左边)的圆括号中未定义的标识符看起
- 先往右看,再往左看
- 当遇到圆括号或者方括号时可以确定部分类型,并调转方向
- 重复2,3步骤,直到结束
示例:
int (*func)(int *) /*编译器的处理*/ /* 第一步:找到未定义的标识符 (func),在这里(int*)已经有定义了,而(func)是我们自定义的标识符,而且没有被定义(因为不知道是什么类型的) 第二步:往右看看到了圆括号,往左看看到了*,确定func为一个指针,然后处理得到 int (int *) 第三步:往右看看到了圆括号,那么可以确定func为一个函数指针,它的参数为一个int指针类型的,然后往左看,看到int,那么确定返回的类型为int类型的 */ int main() { int (*p2)(int *, int (*f)(int *)); /*首先找到p2,然后找到*p2,然后判断p2指向函数, 然后看到第二个参数找到一个未定义的f,然后找到*f,然后找到f指向函数, 然后找到f指向的函数有一个参数为int*类型的,然后找到f指向的函数的返回值为int类型, 然后找到p2指向的函数有两个参数为int*和指向函数的指针,然后找到p2指向的函数的返回值为int类型的*/ int (*p3[5])(int*); /*用上述方法得到p3为一个包含5个元素的数组, 每个元素都是一个函数指针, 函数指针指向的类型为int(int*)*/ return 0; }