函数类型
C语言中的函数有自己特定的类型
函数类型由返回值,参数类型,参数个数共同决定
参数类型和参数个数隐含了另一个条件:参数顺序
例:int add(float i, char j) 的类型为int(int, int),其返回值类型是int,有两个参数,第一个参数float,第二个参数char
int ff(double e, int i); //ff函数类型为int(double, int)
int ff(int i, double e); //gg函数类型为int(int, double)
因为函数参数顺序不同,所以这两个函数类型不同
C语言中通过typedef为函数类型重命名
typedef type name(parameter list)
例: typedef int f(int, int); //定义了一个函数类型f,指的是int(int, int)这类型的函数
typedef void p(int); //定义了一个函数类型p,指的是void(int)这类型的函数
函数指针
函数指针用于指向一个函数
函数名是执行函数体的入口地址
可通过函数类型定义函数指针:FuncType*pointer;
也可以直接定义:type (*pointer)(parameter list);
.pointer为函数指针变量名
.type为指向函数的返回值类型
.parameter list为指向函数的类型参数列表
例1:
#include <stdio.h>
typedef int(FUNC)(int); //把一个int(int)函数类型重定义为FUNC
int test(int i) //test函数类型也为int(int)
{
return i * i;
}
void f() //f函数类型为void()
{
printf("Call f()...\n");
}
int main()
{
FUNC* pt = test; //test函数类型与重定义的FUNC一致,函数名test就是test函数的入口地址,pt是FUNC类型的函数指针,该指针指向test函数
void(*pf)() = &f; //偷懒的方式定义了一个函数指针pf,指向的函数类型为void(),因此可以把f函数的地址赋给pf,使pf指向f函数
pf(); //新式方法函数调用
(*pf)(); //老式方法函数调用
printf("Function pointer call: %d\n", pt(2)); //pt(2)等价于直接调用test(2)
}
注:对函数名取地址的意义和函数名本身的意义相同,即f和&f意义相同,test和&test意义相同,这一点函数名和数组名不同,主要是历史原因导致,老的编译器按&f的方式,因为这样写起来麻烦,故新的编译器按照直接f的方式,为了兼容老的规则,所以两种方式都支持回调函数
回调函数是利用函数指针实现的一种调用机制
回调机制原理
.调用者不知道具体事情发生的时候需要调用的具体函数
.被调函数不知道何时被调用,只知道被调用后需要完成的任务
.当具体事情发生时,调用者通过函数指针调用具体函数
回调机制将调用者和被调函数分开,两者互不依赖
例2:
#include <stdio.h>
typedef int(*FUNCTION)(int); //FUNCTION是指针类型
int g(int n, FUNCTION f) //f是一个指向int(int)类型的函数指针,g就是调用者,f就是被调函数
{
int i = 0;
int ret = 0;
for(i=1; 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()
{
printf("x * f1(x): %d\n", g(3, f1)); //g(3, f1)这么写叫注册,把f1作为参数注册给g,g就可以知道f1具体是什么,然后g就可以工作了
printf("x * f2(x): %d\n", g(3, f2));
printf("x * f3(x): %d\n", g(3, f3)); //当发生这个事件时,调用者g去调用f3函数
}
右左法则
1.从最里层的括号中未定义的标示符看起
2.首先往右看,再往左看
3.当遇到圆括号或者方括号时可以确定部分类型,并调转方向
4.重复2,3步骤,知道阅读结束
例3:
int (*p2)(int*, int (*f)(int*));
int (*p3[5])(int*);
int (*(*p4)[5])(int*);
int (*(*p5)(int*))[5];
太麻烦,有空再写