函数是有地址的,因为函数的机器语言实现由载入内存的代码组成。指向函数的指针中储存着函数代码的起始处的地址。声明一个数据指针时,必须声明指针所指向的数据类型。声明一个函数指针时,必须声明指针指向的函数类型。为了指明函数类型,要指明函数签名,即函数的返回类型和形参类型。
在c语言中声明以一个指向函数的指针格式为:
数据类型 (指针)(形参);
如:
char (*pf)(char *) //pf是指向函数的指针
char ToUpper(char *);//小写转大写字母函数
pf = ToUpper;//使pf指向函数ToUpper
从该声明中可以看出,第一队圆括号把*
和pf
括起来,表明pf
是一个指向函数的指针。因此,(*pf)
是一个参数列表为(char *)
,返回值类型为char
的函数。由于运算符的优先规则,在声明函数指针时必须把*
和指针名括起来。如果省略第一个圆括号就会导致完全不同的情况,如:
char *pf(char *);//很显然,这是一个返回值类型为char的函数
声明了函数指针后,可以把类型匹配的函数地址赋给它,在这种上下文中,函数名可以用于表示函数的地址:
void ToUpper(char *);
void ToLower(char *);
int round(double);
void (*pf)(char *)
pf = ToUpper; //有效,ToUpper是该类型的函数地址
pf = ToLower; //有效,ToLower是该类型的函数地址
pf = round; //无效,round与指针类型不匹配
pf = ToLower(); //无效,ToLower()不是地址
最后一条语句是无效的,因为ToLower()不是地址。指针pf
可以指向其他带char*
类型参数,返回值是void
类型的函数,不能指向其他类型的函数。
ANSI标准下,两种函数指针访问函数的方法:
void ToUpper(char *);
void *pf(char *);
char mis[] = "Nina Metier";
pf = ToUpper; //把ToUpper的地址赋值给pf
(*pf)(mis); //第一种写法;相当于ToUpper(mis);
pf(mis); //第二种写法;相当于ToUpper(mis);
参考资料:
《C Primer Plus》