对于函数指针和typedef的结合运用
实质:函数指针实质是一个指针,并不是函数,函数有自己的函数体,而指针只是一个变量
指针函数和函数指针的区别:
指针函数: 实质:是一个函数,有自己的函数体
格式:数据类型关键字 *xxx(形参)
{
函数体;
}
函数指针: 实质:是一个指针,一个变量,常用来调用函数
格式:数据类型关键字 (*指针名)(形参)
功能:指向函数的指针可用于调用它所指向的函数。可以不需要使用解引用操作符,而直接通过指针调用此函数。
示例1:
typedef void FUN (char , int);
void (*pf)(char, int);//声明一个函数指针pf,指向一个返回值为0带有(char,int)两个形参的函数
FUN fun; //实际就是声明一个void fun(char,int)的函数
pf=fun;
两种调用方法如下:
(*pf)('c',90); // 显式调用
pf('c',90); // 隐式调用
示例 2:通过指针调用函数
1. #include <stdio.h>2.3. 2. // 声明一个函数指针,指向的函数形参带有一个char类型,一个int类型,返回类型为 void 3. void (*pf)(char, int); 5. // 声明一个函数,形参为一个 char 类型,一个 int 类型,返回类型为 void 6. void fun(char ,int); 7. int main() 8. { 9. pf=fun; //函数指针 pf 赋值为 fun 函数的地址(函数名代表函数的地址) 10. (*pf)('c',90); //调用 pf 指向的函数 11. pf('a',80); 12. } 13. void fun(char a,int b) 14. { 15. printf("the argument is %c and %d\n",a,b); 16. }
运行结果: the argument is c and 90
the argument is a and 80
返回指向函数的指针
函数可以返回指向函数的指针,但是,正确写出这种返回类型相当不容易,例如:
int (*ff(int))(int*,int);
要理解函数指针声明的最佳方法是从声明的名字开始由里而外理解。要理解该声明的含义,首先观察“ff(int)”
是将 ff 声明为一个函数,它带领有一个 int 型的形参。该函数返回“int (*)(int*,int)”它是一个指向函数的指针,所指向的函数返回 int 型并带有两个分别为 int *型和 int 型的形参。
使用 typedef 可使该定义更简明易懂:
typedef int (*PF)(int *,int);
PF ff(int);
示例:
#include <iostream> using namespace std; typedef void (*callback)(int x); // 定义一个函数指针类型 void myFunc1(int x) // myFunc1 的声明要与callback一样 { cout << "This is myFunc1 " << x << endl; } void myFunc2(int x) { cout << "This is myFunc2 " << x << endl; } void callMyFunc(callback cb, int x) // 把函数指针类型当做调用函数参数类型 { cb(x); } int main() { callMyFunc(myFunc1, 1); callMyFunc(myFunc2, 2); return 0; }
下面举几个typedef和函数指针结合使用的例子:
左边第一个运行出错 右边两个正确
出错原因:
typedef定义的pf是一种void (*)(int)的函数指针类型,pf定义的是指针(它是一个数据类型关键字,类似于int)。
用pf去声明fun肯定会出错,pf fun,是定义fun为一个函数指针变量(可以理解为函数名),而不是声明函数,右边两个是正确的。
函数名是可以作为函数指针变量,作为函数的入口地址,但是函数名不仅仅是这种作用。
函数名相当于表示函数的入口地址,我们调用时通过函数名,让程序跳转到对应函数处开始执行
还可这样使用:
void (*signal(int signum,void(* handler)(int)))(int); 等价于下面两行
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler)
运行结果: fdsfsfsf1
fdsfsfsf3
解剖一下signal函数,理解函数指针和typedef
void (*signal(int signum,void(* handler)(int)))(int); 等价于下面两行
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler)
分析:先分析第一行,看到这一串的函数声明,不要慌,从内而外一点一点分析:
1. signal(int signum,void(* handler)(int))这是一个函数,函数名为signal
(1) 第一个形参:int signum,是一个整形变量;
(2) 第二个形参:void(*handler)(int),这是一个函数指针,指向:返回值为void型,且带一个int型的形参的函数。
也就是说,这个形参,是一个指针,或者说是一个地址,可以理解为这个形参是函数名,因为函数名是函数的入口
地址。里面分析完了。
2. signal函数的外面是 void(*)(int),想一想,在定义或者声明函数的时候,都需要说明函数返回值的类型,这个signal
函数的形参已经明确了,但是返回值还不知道,这个void(*)(int)就是返回值类型,这个类型是一个函数指针,碰巧的是,
这个函数指针指向的函数类型和signal的第二个形参指向的类型相同,都是指向:返回值为空,且带一个int类型形参的函数。
3. 因此先用typedef定义一种数据类型,这个类型就是void(*)(int),将这种类型定义为,或者说是起名别,叫做sighandler_t
sighandler_t = void(*)(int),所以可以将void(*)(int)类型的函数,在声明或者定义的时候用sighandler_t。
4. signal函数返回值为void(*)(int)型,用sighandler_t代替,第2个形参是void(*)(int)型,用sighandler_t代替。