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

1.定义

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

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

2.取别名

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

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

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

 cmpFun pf = someFunction;
cmpFun pf = &someFunction;

下面是一个测试代码:

 #include <stdio.h>

 void myCmp(int a,int b)
{
printf("%d\t%d\n",a,b);
} typedef void (*PF)(int a, int b);
PF pf = myCmp; int main(void)
{
(*pf)(1,2);
pf(1,2);
//两种访问方式都没问题
return 0;
}

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

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

 #include <stdio.h>

 void myCmp(int a,int b)
{
printf("%d\t%d\n",a,b);
} typedef void (*PF)(int a, int b);
PF pf = myCmp; int main(void)
{
pf(1,2);
printf("%p\t%p\n",myCmp,&myCmp);
((PF)(0x00401610))(1,2);
return 0;
}

上面代码的打印结果为:

 1       2
00401610 00401610
1 2

4.回调函数

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

 #include <stdio.h>

 void myCmp(int a,int b)
{
printf("%d\t%d\n",a,b);
}
void prin(void (*p)(int a,int b))
{
p(1,2);
} int main(void)
{
prin(myCmp);
return 0;
}

5.函数指针数组

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

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

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

 #include <stdio.h>
void func1()
{
printf("void func1()\n");
}
void func2()
{
printf("void func2()\n");
}
void func3()
{
printf("void func3()\n");
} int main(void)
{
int i = 0;
void (*p[3])(void) = {func1,func2,func3};
for(;i<3;i++)
(p[i])();
return 0;
}

6.拓展

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

思考以上代码的意义!

最新文章

  1. 不同java 版本的新功能
  2. maven nexus 3 third party 构件上传
  3. 平衡二叉树(AVL)java实现
  4. js中iframe的用法
  5. redis内存管理代码的目光
  6. scanf函数与scanf_s函数
  7. ZOJ 3696 Alien&#39;s Organ 概率论 泊松分布
  8. 单元测试框架 unittest 的运行方法if __name__ == &#39;__main__&#39;: unittest.main()
  9. Screen命令安装使用教程
  10. udt通信java
  11. LeetCode 142. Linked List Cycle II 判断环入口的位置 C++/Java
  12. L2-027. 名人堂与代金券
  13. (转)mysql升级5.5.20时遇到的问题:1548-Cannot load from mysql.proc. The table is probably corrupted
  14. MySQL8.0手动安装心得。
  15. python-day15函数递归
  16. Vibrator震动
  17. 我在GitHub Pages托管静态博客啦~
  18. 并发编程---线程 ;python中各种锁
  19. USACO16OPEN_248&amp;&amp;USACO16OPEN_262144_KEY
  20. 005-环境安装【docker、fabric】

热门文章

  1. HDU 5832A water problem
  2. CANopen——总线基本知识
  3. Gamma的完全理解
  4. COCI2012 TOY
  5. E20170606-hm
  6. 分布式事务(三)mysql对XA协议的支持
  7. java程序死锁,3种方式快速找到死锁代码
  8. object-c中实现特定一个或者多个页面横竖屏,其他界面保持竖屏显示。
  9. Manacher BestCoder Round #49 ($) 1002 Three Palindromes
  10. C#将类对象转换为字典