(C/C++学习)16.函数指针

说明:函数指针,顾名思义就是指向函数的指针。C/C++中函数名的本质其实就是一段代码段空间的首地址。

1.定义

如下的 pf 就是一个函数指针,指向所有返回类型为 int,并带有两个 const int 参数的函数。需要注意的是 *pf 两边的括号不能少,否则下面定义就变成声明一个函数 pf其返回类型为 int *, 带有两个 const int 参数。

  1 int (*pf)(const int, const int);

 

2.取别名

如果每次都像上面那样来声明一个函数指针,那样就显得太复杂了,我们可以通过取别名的方式来简化声明复杂程度,如下:

  1 typedef int (*cmpFun)(const int, const int);

这样,cmpFun 就成了一种数据类型,可以用它来声明和定义形如上面 pf 那样的函数指针,比如:

  1 cmpFun pf = someFunction;
  2 cmpFun pf = &someFunction;

下面是一个测试代码:

  1 #include <stdio.h>
  2 
  3 void myCmp(int a,int b)
  4 {
  5     printf("%d	%d
",a,b);
  6 }
  7 
  8 typedef void (*PF)(int a, int b);
  9 PF pf = myCmp;
 10 
 11 int main(void)
 12 {
 13     (*pf)(1,2);
 14     pf(1,2);
 15     //两种访问方式都没问题
 16     return 0;
 17 }

 

3.函数名作为地址的用法

上面提到了,函数名的本质是一个地址,那如果我们拿到这个地址,是否可以直接调用相应的函数呢?答案是肯定的!如下代码,先打印出函数名所代表的地址,然后将其强转成 PF 函数指针类型,然后在对其进行函数的调用。

  1 #include <stdio.h>
  2 
  3 void myCmp(int a,int b)
  4 {
  5     printf("%d	%d
",a,b);
  6 }
  7 
  8 typedef void (*PF)(int a, int b);
  9 PF pf = myCmp;
 10 
 11 int main(void)
 12 {
 13     pf(1,2);
 14     printf("%p	%p
",myCmp,&myCmp);
 15    ((PF)(0x00401610))(1,2);
 16     return 0;
 17 }

上面代码的打印结果为:

  1 1       2
  2 00401610        00401610
  3 1       2

 

4.回调函数

当函数作为参数而发起的调用函数的过程,就叫作函数的回调。函数的回调其实也是利用了函数指针这一概念。下面是一个回调示例:

  1 #include <stdio.h>
  2 
  3 void myCmp(int a,int b)
  4 {
  5     printf("%d	%d
",a,b);
  6 }
  7 void prin(void (*p)(int a,int b))
  8 {
  9     p(1,2);
 10 }
 11 
 12 int main(void)
 13 {
 14     prin(myCmp);
 15     return 0;
 16 }

5.函数指针数组

如下定义一个返回值和参数皆为 void 的函数指针数组:

  1 void (*funcArray[N])(void);

函数指针的一个用法出现在菜单驱动系统中。例如程序可以提示用户输入一个整数值来选择菜单中的一个选项。用户的选择可以做函数指针数组的下标,而数组中的指针可以用来调用函数。下面是一个程序示例:

  1 #include <stdio.h>
  2 void func1()
  3 {
  4     printf("void func1()
");
  5 }
  6 void func2()
  7 {
  8     printf("void func2()
");
  9 }
 10 void func3()
 11 {
 12     printf("void func3()
");
 13 }
 14 
 15 int main(void)
 16 {
 17     int i = 0;
 18     void (*p[3])(void) = {func1,func2,func3};
 19     for(;i<3;i++)
 20         (p[i])();
 21     return 0;
 22 }
 23 
 24 

6.拓展

  1 (*(void(*) ()) 0)()

思考以上代码的意义!

原文地址:https://www.cnblogs.com/tuihou/p/9858395.html