1. 函数指针
函数指针:指向函数的指针,存放函数地址的指针。
&func_name 取到的就是函数的地址;
直接用 func_name 也可以得到函数的地址;
数组名 &数组名 两者不等价
函数名 &函数名 两者等价
如何定义一个函数指针变量呢?
int (*pf)(int, int) = &Add;
这里的Add是一个函数名,函数接收两个int型的参数,函数的返回类型也是int.
因此函数指针变量定义应该是:
函数返回类型
(*指针名称
) ( 函数传参类型1
, 函数传参类型2
, ...)= &函数名
;
定义和使用的例子:
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (*fp2) (int, int) = &Add;
int ret = (*fp2)(5, 4);
//也可以这么来调用:int ret = fp2(5, 4);
printf("5 + 4 =%d\n", ret);
}
(*fp2)(5, 4) 和 fp2(5, 4) 都可以调用函数,这说明那颗星是一个摆设!
题目1:如何对下面的代码进行解析?
(*(void(*)())0) ();
void(*p)()
可以看做是对函数指针p进行声明的语法,这里p的类型就是 void(*)()
,所以 (void(*)())0
就是对 0 进行强制类型转换,把他转换成一个函数指针!(*(void(*)())0)
是对函数指针进行解引用,因此这段代码的作用就是调用0地址处的函数:该函数无参数,返回类型是 void。
题目2: 如何对下面的代码进行解析?
void (* signal(int, void(*)(int))) (int);
- 首先从
signal
入手,他首先和()
进行结合,说明他是一个函数; signal
函数有两个参数,参数1是int
型的,参数2是void(*)(int)
型的,也就是函数指针型的;- 函数名,函数参数都确定了,拿掉这部分,剩下的就是函数返回值类型,剩下了什么呢?是:
void (*) (int)
,可见signal
函数的返回类型是一个函数指针。
因此上述语句其实就是对 signal
函数进行声明的语句。
自己实现了一个这样的 signal
函数:
void (* signal(int, void(*)(int))) (int);
void wash(int n)
{
printf("I will wash %d kg vegetables today.\n", n);
printf("after vegetables are washed, please start cooking!\n");
}
void cooking(int n)
{
printf("I will cooking %d kg vegetables.\n", n);
}
void (* signal(int n, void(*p)(int))) (int)
{
p(n);
return cooking;
}
int main()
{
int n = 5;
void (*w) (int n);
w = signal(n, wash);
w(n);
return 0;
}
注意,上述 signal
函数的声明如果这样写是不被允许的:
void (*)(int) signal(int, void(*)(int)); // 不被允许的写法,虽然更容易读懂
但是有没有更好的写法呢?当然是有的:
typedef void(*pfun_t)(int); // 对void(*)(int)的函数指针类型重命名为 pfun_t
pfun_t signal(int, pfun_t);
这样,上述代码就可以简化成:
typedef void(*pfun_t)(int); // 对void(*)(int)的函数指针类型重命名为 pfun_t
pfun_t signal(int number, pfun_t call_pfun);
void wash(int n)
{
printf("I will wash %d kg vegetables today.\n", n);
printf("after vegetables are washed, please start cooking!\n");
}
void cooking(int n)
{
printf("I will cooking %d kg vegetables.\n", n);
}
pfun_t signal(int n, pfun_t p)
{
p(n);
return cooking;
}
int main()
{
int n = 5;
void (*w) (int n);
w = signal(n, wash);
w(n);
return 0;
}
2. 函数指针数组
函数指针数组里面可以存放同类型的函数指针
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int main()
{
int (* pf_arr[2]) (int, int) = {Add, Sub};
int ret = pf_arr[1](5, 3);
printf("%d\n", ret);
return 0;
}
这里 pf_arr
的声明也可以这样:
typedef int (add_or_sub) (int x, int y);
add_or_sub *pf_arr[2] = {Add, Sub};
还可以这样:
typedef int (* add_or_sub) (int x, int y);
add_or_sub pf_arr[2] = {Add, Sub};
3. 指向函数指针数组的指针
指向函数指针数组的指针是一个 指针
,指针指向一个 数组
,数组的元素都是 函数指针
.
int (* arr[2]) (int, int) = {Add, Sub}; // p2 是一个函数指针数组
int (* (*parr)[2]) (int, int) = &arr; // p3就是一个指向【函数指针数组】的指针
总结, 如果一个指针parr指向了一个数组arr,那么这个指针可以以这种方式进行声明:在等号左边,把声明arr的代码拷贝过来,用(*parr)来对该声明中的arr进行字符串替换;等号右边替换成&arr。