一、基本概念
数组名:本质是指向数组第一个元素的常量指针,即数组首地址
函数名:本质是指向函数第一条指令的常量指针,即函数首地址
函数指针:保存了函数首地址,可以看做函数的别名
二、函数指针的声明方法
type (*func)(type &, type &)
1、该语句声明了一个指针func,它指向了一个函数;
2、该函数带有2个type型参数,并返回一个type型的值;
p.s. tpye类型可以看做int或者float等C++类型
3、可以把整个函数看做一个数据类型
tpye func(type, type)
指针变量func就指向这样的数据类型
三、注意事项
1、一个指向函数的指针必须保证该函数被定义了,且被分配了内存,
否则它指向一个空地址,这可是大忌!
2、特别注意第一个括号的位置,如果把括号去掉
type *func(type &, type &)
就变成了一个返回type *类型的函数了
四、函数指针应用举例
1、通过函数指针调用函数
# include <stdio.h>
void f(int x)
{
printf("%d\n", x);
}
int main()
{
f(10); //直接调用函数f
void (*p)(int); //定义一个函数指针p
p = f; //对指针变量p赋值,函数名f即为函数首地址 ,p=&f也正确
(*p)(20); //通过指针而非函数名调用函数
return 0;
}
2、函数指针的typedef用法
typedef void (*PINT)(int) ; //声明该函数结构void f(int)为一个数据类型
PINT是该数据类型的名字
//注意区别于结构体的typedef用法
PINT p;
p = f;
3、函数指针作为函数参数
设计一个CallMyFun函数,这个函数可以通过参数中的函数指针值不同来分别调用
MyFun1、MyFun2、MyFun3这三个函数(注:这三个函数的定义格式应相同)。
# include <stdio.h>
typedef void (*PM)(int); //定义新的函数数据类型为PM
void CallMyfun(PM p, int x) //函数指针作为形参
{
p(x);
}
void MyFun1(int x)
{
printf("MyFun1 = %d\n", x);
}
void MyFun2(int x)
{
printf("MyFun2 = %d\n", x);
}
void MyFun3(int x)
{
printf("MyFun3 = %d\n", x);
}
int main()
{
CallMyfun(MyFun1, 10);
CallMyfun(MyFun2, 20);
CallMyfun(MyFun3, 30);
return 0;
}
五、再次深入学习
1、*(int*)&p ----这是什么?
void Function()
{
printf("Call Function!\n");
}<br>
int main()
{
void (*p)(); //定义函数指针变量p
*(int*)&p=(int)Function;//&p求指针变量p的地址,这是一个32位的二进制数
//(int *)&p表示将地址强制转化为指向int型数据的指针
//(int)Function表示将函数入口地址强制转换成int型数据
(*p)();
return 0;
}
2、(*(void (*)(void))(0x30700000)()--这是什么?
void (*reset)(void) = (void (*)(void))0
reset();
等式左边为定义函数指针reset;
等式右边为强制类型转换,将数值“0”强行转换为函数指针地址“0”;
下一句表示调用函数reset(),从地址"0"处开始执行;
举例:
void (*theUboot)(void); //定义函数指针theUboot
theUboot = (void (*)(void))(0x30700000);//将绝对地址0x30700000
强制转换为函数指针地址,然后赋给theUboot
theUboot(); //调用函数theBoot()
p.s.以上代码可以合并为下面一行代码:
(*(void (*)(void))(0x30700000)();
3、总结
其实函数指针与普通指针没什么差别,只是指向的内容不同而已。
使用函数指针的好处在于,可以将实现同一功能的多个模块统一起来标识,这样一来更容易后期的维护,系统结构更加清晰。或者归纳为:便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开。
六、函数指针数组
例:char * (*pf[3])(char *)
函数指针数组本质是一个数组,这里pf就是数组名;
该数组有3个元素pf[0]、pf[1]、pf[2],分别存放了3个函数指针;
指向的3个函数的返回值都是 char *,形参都是 char *;
程序示例:
# include <stdio.h>
void fun1(char * p)
{
printf("%s\n", p);
}
void fun2(char * p)
{
printf("%s\n", p);
}
void fun3(char * p)
{
printf("%s\n", p);
}
int main()
{
void (*pf[3])(char *); //定义函数指针数组
pf[0] = fun1;
pf[1] = fun2;
pf[2] = fun3;
pf[0]("fun1"); //形参为字符串"fun1",传递给形参字符串首地址
pf[0]("fun2");
pf[0]("fun3");
return 0;
}
七、函数指针数组指针
例 char * (*(*pf)[3])(char * p);
函数指针数组指针本质是一个指针;
该指针指向一个数组;
该数组里面存放的都是指向函数的指针;
程序示例:
#include <stdio.h>
#include <string.h>
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");
return 0;
}