第一部分 什么是函数指针
1.1 函数指针概念
1.2 函数指针与指针函数,数组指针与指针数组
1.3 函数指针的作用
第二部分 函数指针的初始化及使用
2.1 初始化函数指针
2.2 函数名究竟是什么
#include <stdio.h>
int
test(
void
);
int
main(
void
)
{
printf(
" test=%p\n"
,test);
printf(
"&test=%p\n"
,&test);
printf(
"*test=%p\n"
,*test);
return
0;
}
int
test(
void
)
{
printf(
"test invoked!"
);
return
0;
}
|


2.3typedef可以用于定义函数指针类型
要说明一下,对于typedef int (*ptf) (double*,char); 注意不要用#define的思维来看待typedef,如果用 #define的思维来看的话会以为 (*ptf)(double*, char)是int的别名,但这样的别名看起来好像又不是合法的名字,于是会处于迷茫状态。实际上,上面的语句把 ptf定义为一种函数指针类型的别名,它和函数指针类型 int (*) (double*, char);等价,也就是说ptf现在也是一种类型。
下面分析一个函数指针和指针函数结合的例子:
void (*signal (int sig, void (*func) (intsiga)) ) ( int siga );
看上去确实有些复杂,让我们来分析。现在要分析的是 signal,因为紧邻 signal的是优先级最高的括号,首先与括号结合,所以 signal为一个函数,括号内为 signal的两个形参,一个为 int型,一个为指向函数的指针。接下来从向左看, *表示指向某对象的指针,它所处的位置表明它是 signal的返回值类型,现在可以把已经分析过的 signal整体去掉,得到 void (*) ( int siga ),很清晰了吧。又是一个函数指针,这个指针与 signal形参表中的第二个参数类型一样,都是指向接受一个 int型形参且不返回任何值的函数的指针。同样地,用 typedef可以将这个声明简化:
typedef void (*p_sig) (int);
p_sig signal(int sig, p_sig func);
这个signal 函数是C语言的库函数,在 signal.h中定义,用来处理系统中产生的信号,是 UNIX/Linux编程中经常用到的一个函数,所以在此单独拿出来讲解。
2.4 函数指针数组
还有一种较为常用的关于函数指针的用法——函数指针数组。假设现在有一个文件处理程序,通过一个菜单按钮来选择相应的操作 (打开文件,读文件,写文件,关闭文件 )。这些操作都实现为函数且类型相同,分别为:
void open( );
void read( );
void write( );
void close( );
现在定义一个函数指针类型的别名
PF: typedef void (*PF) ( );
把以上4种操作取地址放入一个数组中,得到:
PF file_options[ ] = {
&open,
&read,
&write,
&close
};
这个数组中的元素都是指向不接受参数且不返回任何值的函数的指针,因此这是一个函数指针数组。接下来,定义一个函数指针类型的指针 action并初始化为函数指针数组的第一个元素: PF* action = file_options;,如果不好理解,可以类比一下 int ia[4] = {0, 1, 2, 3}; int *ip = ia;,这里PF 相当于int,这样应该比较好懂了。通过对指针 action进行下标操作可以调用数组中的任一操作,如: action[2]( )会调用 write操作,以此类推。在实际中,指针 action可以和鼠标或者其他 GUI对象相关联,以达到相应的目的。
2.5 复杂的函数指针声明
2. ANSI C标准将f ( )认为是(*f)( )的简写形式,并且推荐使用f ( )形式,因为它更符合函数调用的逻辑。
3. 关于函数指针的加减运算没有意义。
4. 在使用中函数名会被转换为指向这个函数的指针,指针的值就是函数的入口地址,函数的地址在编译期是未知的,而是在链接时确定的。
5. 对于复杂的函数指针声明,可以用右左法则来进行分析。