函数指针的定义
函数指针就是指向代码入口地址的指针,是指向函数的指针变量。所以“函数指针”本身是一个指针变量,并且该指针指向的是函数。C语言在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量之后,就可以用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是一致的。函数指针有两个用途:调用函数和做函数的参数。
函数指针的声明和使用
函数指针的声明方法为:
数据类型标志符 (指针变量名) (形参列表);
“函数类型”说明函数的返回类型,由于“()”的优先级高于“*”,所以指针变量名外的括号必不可少,后面的“形参列表”表示指针变量指向的函数所带的参数列表。
例如:
int function(int x, int y); /*声明一个函数*/
int(*f)(int x, int y); /*声明一个函数指针*/
f = &function; /*将function 函数的首地址赋给指针f*/
f = function; /*将function 函数的首地址赋给指针f*/
注意点:
1. 赋值时函数function不带括号,也不带参数,由于函数名 function就代表函数的首地址,因此经过赋值以后,指针 f 就指向函数function(int x, int y) 的代码的首地址。
2. 为什么使用 f = &function 和 f = function都可以进行赋值呢?这是因为在C语言中,函数名被编译之后其实就是一个地址,所以这两种用法没有本质的差别。
3. 函数指针的原型(参数和返回值)必须要和指向的函数是一致的。所以,通常,要声明指向特定类型的函数的指针,可以先编写这种函数的原型,然后用(*pf)替换函数名,这样pf就是这类函数的指针。
示例代码
char * fun(char * p1, char * p2)
{
int i = 0;
i = strcmp(p1, p2);
if (0 == i)
{
printf("true\n");
return p1;
}
else
{
printf("false\n");
return p2;
}
}
void main()
{
char *(*pf)(char *p1, char *p2);
// pf = &fun;
pf = fun;
(*pf)("aa", "bb");
// (*pf)("bb", "bb");
while (1);
}
函数指针数组
根据函数指针的表达式
int(*pf)(int x, int y); /*声明一个函数指针*/
把pf这个指针存储在一个数据里面,
int(*pf[10])(int x, int y); /*声明一个函数指针数组*/
这是一个数组,数组名为 pf ,数组内存储了10个指向函数的指针。这些指针指向一些返回值类型为int, 参数也为int的字符的指针的函数。
函数指针数组示例代码
char *fun1(char *p)
{
printf("%s\n", p);
return p;
}
char *fun2(char *p)
{
printf("%s\n", p);
return p;
}
char *fun3(char *p)
{
printf("%s\n", p);
return p;
}
int main()
{
char *(*pf[3])(char *p);
pf[0] = fun1; //可以直接用函数名
pf[1] = &fun2; //可以用函数名加上取地址符
pf[2] = &fun3;
pf[0]("fun1");
pf[1]("fun2");
pf[2]("fun3");
while (1);
}
函数指针数组的指针
函数指针数组的指针定义:
char *(*(*pf)[3])(char * p);
注意,这里的 pf 和上一节的 pf 就完全是两码事了。上一节的 pf 并非指针,而是一个数组名;这里的 pf 确实是实实在在的指针。这个指针指向一个包含了 3 个元素的数组;这个数字里面存的是指向函数的指针;这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。
示例代码
char *fun1(char *p)
{
printf("%s\n", p);
return p;
}
char *fun2(char *p)
{
printf("%s\n", p);
return p;
}
char *fun3(char *p)
{
printf("%s\n", p);
return p;
}
int main()
{
char * (*a[3])(char *p);
char * (*(*pf)[3])(char * p);
pf = &a;
a[0] = fun1;
a[1] = &fun2;
a[2] = &fun3;
pf[0][0]("fun1");
pf[0][1]("fun2");
pf[0][2]("fun3");
while (1);
}
((void()())0)()的解析
1. void (*)(), 可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。
2. (void(*)())0,这是将0强制转换为函数指针类型。这个函数没有参数,没有返回值。
3. (*(void(*)())0),这是取0地址开始的一段内存里面的内容,其内容就是保存在首地址为0的一段区域内的函数。
4. (*(void(*)())0)(),这是函数调用。