《征服 C 指针》摘录4:函数 与 指针
一、指向函数的指针
函数名可以在表达式中被解读成“指向函数的指针”
,因此,正如代码清单 2-2 的实验那样,写成 func 就可以取得指向函数的指针。
“指向函数的指针”本质上也是指针(地址),所以可以将它赋给指针型变量。
比如有下面的函数原型:
int func(double d);
保存指向此函数的指针的变量的声明如下:
int (*func_p)(double);
然后写成下面这样,就可以通过 func_p 调用 func,
int (*func_p)(double); // 声明
func_p = func; // 将func 赋给func_p
func_p(0.5); // 此时,func_p 等同于func
将“指向函数的指针”保存在变量中的技术经常被运用在如下场合:
- GUI 中的按钮控件记忆“当自身被按下的时候需要调用的函数”
- 根据“指向函数的指针的数组”对处理进行分配
后者的“指向函数的指针的数组”,像下面这样使用:
int (*func_table[])(double) = {func0,func1,func2,func3,
};
┊
func_table[i](0.5); // 调用func_table[i]的函数,参数为0.5
使用上面的写法,不用写很长的 switch case,只需通过 i 的值就可以对处理进行分配。
哦?不明白为什么?
确实,像
int (*func_p)(double); // 指向函数的指针
还有,
int (*func_table[])(double); // 指向函数的指针的数组
这样的声明,是不能用普通的方法来读的。
关于这种声明的解读方式,会在后面进行说明。
二、关于指向函数的指针引起的混乱
正如上面说明的那样,对于 C 语言,表达式中的函数名可以被解读成“指向函数的指针”。
在信号处理、事件驱动的程序中,这种特性往往以回调函数的形式被使用。
/*如果发生SIGSEGV(Segmentation falut),回调函数segv_handler */
signal(SIGSEGV, segv_handler);
可是,如果基于之前说明过的 C 语言声明规则,int func()这样的声明会被解释为“返回 int的函数”,如果 函数名在表达式中,只是取出 func,则解释成“指向返回 int 函数的指针”,是不是感觉很怪异?如果一定要使用指向函数的指针,必须要写成&func。
对于上面信号处理的函数,写成
signal(SIGSEGV, &segv_handler);
这样,实际上也能顺利地执行。
相反,像
void (*func_p)();
这样,变量 func_p 声明为指向函数的指针,进行函数调用的时候,可以写成
func_p();
但是像 int func()这种声明,都是用 func()这样的方式进行调用的,从对称性的角度考虑,对于 void (*func_p)(),必须要写成
(*func_p)();*
* 早期的 C 语言中,好像也只能这么写……
这样也是能毫无问题地执行的。
是不是感觉 C 语言的关于指向函数的指针的语法比较混乱?
混乱产生的原因就是:“表达式中 的函数可以解读成‘指向函数的指针’”这个意图不明的规则(难道就是为了和数组保持一致?)。
为了照顾到这种混乱,ANSI C 标准对语法做了以下例外的规定:
- 表达式中的函数自动转换成“指向函数的指针”。但是,当函数是地址运算符&或者 sizeof 运算符的操作数时,表达式中的函数名不能变换成“指向函数的指针”。
- 函数调用运算符()的操作数不是“函数”,而是“函数的指针”。
如果对“指向函数的指针”使用解引用*,它暂时会成为函数,但是因为在表达式中,所以它会被瞬间地变回成“指向函数的指针”。
结论就是,即使对“指向函数的指针”使用*运算符,也是对牛弹琴,因为此时的运算符*发挥不了任何作用。
因此,下面的语句也是能顺利执行的,
(**********printf)("hello, world\n"); // 无论如何,*就是什么也没做
延伸阅读:
《征服 C 指针》摘录1:什么是空指针?区分 NULL、0 和 '\0'
《征服 C 指针》摘录2:C变量的 作用域 和 生命周期(存储期)
《征服 C 指针》摘录3:数组 与 指针
《征服 C 指针》摘录4:函数 与 指针
《征服 C 指针》摘录5:函数形参 和 空的下标运算符[]
《征服 C 指针》摘录6:解读 C 的声明
《征服 C 指针》摘录7:练习——挑战那些复杂的声明
《征服 C 指针》摘录4:函数 与 指针相关推荐
- 函数指针(指向函数的指针)
目录 1. 函数指针(指向函数的指针) 1.1 使用函数指针(指向函数的指针) 1.2 重载函数的指针 1.3 函数指针形参(形参是指向函数的指针) 1.4 使用类型别名和 decltype 简化函数 ...
- Day17 指针变量做函数形参 指针函数 函数指针
1. 指针变量做函数形参 1.1指针变量做一维数组形参 首先先了解如何定义一个一维数组指针 int arr[5] = {1, 2, 3, 4, 5};//定义一个一维数组 int *parr = ar ...
- 【C语言】函数指针(指向函数的指针)
文章目录 1. 函数指针的定义 2. 函数指针的定义形式 2.1 一般定义方法 2.2 加上typedef关键字的定义 3.利用函数指针调用其所指向的函数 3.1 情况1:一般调用 3.2 情况2:函 ...
- 初论函数指针、指针函数、指针的指针
一.指针函数 1.定义 指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 函数返回值类型 函数名(参数表) int * f(int x,int y); //函数返回值类型是in ...
- 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)
相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...
- (转)函数指针,指针函数,指向函数的指针,返回指针的函数
摘要: 在学习C语言时,一个比较容易混淆的概念就是函数指针.指针函数.返回值为指针的函数.本文将对这三个概念进行区分.指针函数就是返回值为指针的函数,两个本质上是同一事物,只是叫法不同.函数指针就是一 ...
- 指针系统学习7-返回指针值的函数
1.返回指针值的函数 一个函数可以带回一个整型值.字符值.实型值等,也可以带回指针型的数据,即地址.其概念与以前类似,只是带回的值的类型是指针类型而已. 这种带回指针值的函数,一般定义形式为 ...
- 数组指针和指针数组,函数指针和指针函数,常量指针和指针常量,常量引用
一.数组指针和指针数组 1.数组指针(行指针) 首先要知道数组指针是指向数组的指针.所以数组指针本质是个指针,只不过指向一个数组而已.格式为:T (*ptr)[]. 注意:"[]" ...
- 【C/C++学习】之七、指向函数的指针
什么是指向函数的指针 函数指针是指向函数的指针变量,不是指向对象的指针!函数指针本身应该是"指针变量": "在C语言中,函数本身不是变量,但可以定义指向函数的指针,这种指 ...
最新文章
- CoLoRMap: Correcting Long Reads by Mapping short reads CoLoRMap:通过映射短读来纠正长读
- Facade模式——设计模式学习笔记
- ISA CMAK 网络访问隔离区
- 分离图片中的隐藏文件方法总结
- 联想服务器网卡型号怎么看,如何通过设备硬件ID判断无线网卡的品牌及型号
- 这10道Java面试题!大部分的人回答不出来
- 关于多线程的一点感想
- Python Pillow(PIL)库的用法介绍(二)
- android的自定义字体,Android 自定义字体方案
- node.js学习笔记之浅谈观察者模式
- Java语言基础:IPO编程模式
- python游戏开发keydown_pygame.KEYDOWN移动对象
- emv交易流程介绍,简易波动指标EMV基础知识介绍:EMV的计算公式_EMV应用法则
- MAC 笔记本快捷键使用总结
- Error: Can't find Python executable python, you can set the PYTHON env variable.解决办法
- VS2013写的程序在Win XP下运行的完美解决方案(百分百成功)
- Ubuntu安装Lua
- PS Suite Studio Android 调试方法
- 天然和合成石墨的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- 模型驱动开发的幻象与现实
热门文章
- 计算机通信网络实验(三) RIP协议原理及配置
- 清华大学王玉计算机,计算机科学技术——人工智能.pdf
- CK-S650-PA60S半导体行业RFID读写器|读卡器N协议详细说明
- 仰望Cosmos星空的明与暗:全面解析ATOM 2.0
- python爬虫解析数据错误_Python网络爬虫数据解析的三种方式
- 通过Python利用ADSL服务器和tinyproxy构建数据自己的动态代理IP池,用django+redis做web服务,提供IP接口
- 气垫车-市场现状及未来发展趋势
- VB.net实现Singleton模式
- Linux下类迅雷的下载神器-uGet 2.0
- ElementUI入门