函数指针,顾名思义,也就是指针,不过这个指针是指向函数的指针。

在【 C 】高级指针话题之高级声明的演进 这篇博文中提到了函数指针的声明等,摘出来:

接下来的一个声明更有趣,但也更容易让人疑惑:

int (*f)();

确定括号的含义是分析这个声明的一个重要步骤。这个声明有两个括号,每对的含义各不相同。第2个括号是函数调用操作符,第1个括号只起到聚组的作用。它迫使间接访问在函数调用之前进行,使 f 成为一个函数指针,它所指向的函数返回一个整型值。

何为函数指针?

程序中的每个函数都位于内存中的某个位置,所以存在指向那个位置的指针是完全可能的。

如果上面的引用不清楚的话,我在试着解释一遍:

int (*f)();

先执行括号里面的内容,也就是间接访问操作,可见 f 是一个指针,可是之后就进行函数调用的操作,可见该指针是还不是一般的指针,该指针指向一个函数,称该指针为函数指针。

函数指针有什么用呢?最常见的两个用途是转换表(jump table)和作为参数传递给另一个函数。但是本博文不涉及其应用,只是简单地了解一下函数指针以及函数指针的初始化!


必须提出,和其他类型的指针一样,简单声明一个函数指针并不意味着可以马上使用,对函数指针执行间接访问之前必须初始化为指向某个具体的函数。而这个过程十分的有意思,下面的代码说明了一种初始化函数指针的方法:

int f( int );
int (*pf)( int ) = &f;

第2个声明创建了一个函数指针并把它初始化为指向函数 f 。这里关键的问题是:在函数初始化之前具有 f 的原型是很重要的,否则编译器就无法检测 f 的类型是否与 pf 所指向的类型一致。

下面更有意思的内容来了:

初始化表达式中的 &(取地址操作符)是可选的,因为函数名被使用时总是由编译器把它转换为函数指针。&操作符只是显式地说明了编译器隐式执行的任务。

在函数指针被声明以及初始化之后,我们就可以使用三种方式来调用函数:

int ans;ans = f( 25 );
ans = (*pf)(25);
ans = pf(25);

这三种方式调用函数完成的功能是完全相同的,这看起来有些荒谬,特别是第三条,而实际上并非如你所想,下面一一道来:

第1条语句简单地使用名字来调用函数,这是我们最常用的调用函数的方法,但它的执行过程可能和你想象的不太一样。函数名f首先被转化为一个函数指针,该指针指定函数在内存中的位置。然后,函数调用操作符()调用该函数,执行开始于这个地址的代码。

第2条语句对pf执行间接访问操作,它把函数指针转化为一个函数名。这个转换并不是真正需要的,因为编译器在执行函数调用操作符之前又会把它转换回去。

第3条语句和前两天语句效果一样,只不过省去了在第1种情况下,编译器把函数名 f 转换为函数指针的过程,这里是直接执行函数在该处的代码。

仔细品味这些说明,真是大开眼界!

【 C 】初识函数指针相关推荐

  1. 从零开始学前端:初识函数,合法属性与自定义属性 --- 今天你学习了吗?(JS:Day2)

    从零开始学前端:程序猿小白也可以完全掌握!-今天你学习了吗?(JS) 复习:从零开始学前端:初识JavaScript - 今天你学习了吗?(JS:Day1) 文章目录 从零开始学前端:程序猿小白也可以 ...

  2. c/c++中的函数指针和指针函数

    定义 1.指针函数,本质是函数,返回值为指针,形如,int *pfun(int, int),由于"*"的优先级低于"()"的优先级,所以等同于int *(pfu ...

  3. 函数指针amp;绑定: boost::functoin/std::function/bind

    see link: https://isocpp.org/wiki/faq/pointers-to-members function vs template: http://stackoverflow ...

  4. 0709 C语言常见误区----------函数指针问题

    1.函数指针的定义 对于函数 void test(int a, int b){ // } 其函数指针类型是void (* ) (int , int), 注意这里第一个括号不能少, 定义一个函数指针,v ...

  5. java跨函数跳转_C语言中将绝对地址转换为函数指针以及跳转到内存指定位置处执行的技巧...

    1.方法一 要对绝对地址0x100000赋值,我们可以用 (unsigned int  * ) 0x100000 = 1234; 那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做? ...

  6. 函数指针(就做个笔记)

    1,函数的地址 #include <stdio.h> int main(){int i=0;printf("main=%p\n",main);printf(" ...

  7. 函数指针--Nginx和Redis中两种回调函数写法

    1.Nginx和Redis中两种回调函数写法 #include <stdio.h>//仿Nginx风格 //结构外声明函数指针类型 typedef void (*ngx_connectio ...

  8. 结构体中定义函数指针

    结构体指针变量的定义,定义结构体变量的一般形式如下: 形式1:先定义结构体类型,再定义变量 struct结构体标识符 { 成员变量列表;- }; struct 结构体标识符 *指针变量名; 变量初始化 ...

  9. C++中函数指针的使用

    A function pointer is a variable that stores the address of a function that can later be called thro ...

最新文章

  1. 2017 ACM/ICPC Asia Regional Xian Online 记录
  2. web 前端基本框架
  3. Kratos技术系列|从Kratos设计看Go微服务工程实践
  4. android 动态contextmenu,在Android中使用ContextMenu与ListView
  5. 2017.9.4 Nim 思考记录
  6. PAT:1013. 数素数 (20) AC
  7. Fiddler图标解释
  8. 小白 白嫖7天百度云网盘会员,高速下载
  9. lammps软件介绍与使用
  10. python程序设计基础董付国 pdf-Python程序设计基础与应用(高等教育规划教材)
  11. 一元二次方程的简单解法
  12. Js逆向:建筑市场监管平台
  13. 递归 (一): 递归思想与 C++ 中的递归函数及两个递归应用示例 (斐波那契, 汉诺塔)
  14. ZZ 自制低成本3D激光扫描测距仪(3D激光雷达),第二部分
  15. 君子签推出AI智能电子合同一体化处理产品,赋能合同业务智能化
  16. 如画的水乡,如画的同里58
  17. jquery+css动画效果-数字跳动
  18. 用计算机实现校正环节采样开关加在哪,计算机控制技术习题—广州工业大学.doc...
  19. 解决新版edge浏览器(109版本)无法正常使用
  20. Intellij IDEA Messages报Information:java: javacTask: 源发行版 8 需要目标发行版 1.8 Information:java: Errors occu

热门文章

  1. Canvas3 汉化QA和BUG反馈
  2. qq在线咨询代码,MSN在线代码,贸易通在线留言源代码!
  3. 对IOC,AOP的理解
  4. document.body.offsetWidth 网页可见区域高宽,offset、client、scroll使用方法详解,页面位置距离
  5. 取得数组中的随机数random.nextInt(index)
  6. springaop事务逻辑原理_太狠了!阿里大牛手写的Spring核心面试笔记:IOC+AOP+MVC+事务...
  7. 手机网页css字体,CSS深入浅出-动态REM(手机专用)
  8. php如何一篇文章替换敏感字,php实现的替换敏感字符串类实例
  9. mysql view none,MySQL笔记之视图的使用详解
  10. 基于RT-Thread开发智能视觉组智能车-乐山师范学院