《征服 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 指针》摘录4:函数 与 指针的更多相关文章
- C语言函数指针(指向函数的指针)
转载:http://c.biancheng.net/cpp/html/3248.html 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常 ...
- C:函数指针、回调函数
函数指针 是一个指针,指向函数的指针,指针存放的都是地址,所以函数指针存放的是函数的地址.数组名就是数组的首地址,函数名就是函数的首地址.与数组类似. 代码demo int (*p) (int ,in ...
- C语言函数指针变量和指针函数以及指针数组
C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址.我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数.然后通过指针变量就可以找到并调用这 ...
- 看懂c/c++ 函数、指针、数组定义
读懂 函数 + 指针 + 数组 c语言运算符机器优先级,看这里 结合运算符优先级,我们试着读懂函数和指针 优先级简单看 表达式提升():一级优先 函数():二级优先 数组[]:二级优先 指针定义*:三 ...
- C 函数指针与回调函数
函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: #inclu ...
- c指针 --笔记2返回指针值的函数
返回指针值的函数 一般带回指针值的函数,定义形式为: int *a (int x, int y); 看这个经典案例: #include <stdio.h> int main(int arg ...
- C语言中函数和指针的參数传递
近期写二叉树的数据结构实验.想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个样例讨论一下c语言中指针作为形參的函数中传递中隐藏的东西. 大家知道C++中有引用的概念,两个 ...
- C++(二十二) — 指针变量、函数指针、void指针
1.指针变量 (1)指针变量必须在初始化后才可以正常使用,初始化就是给他分配一个有效的数据地址. 先初始化,后使用. (2)指针可以进行加减运算,++ 或者 --:将指针的位置向前或者向后移动一个数据 ...
- C++指向函数的指针
直接上代码: #include<iostream> #include<string> #include<vector> using namespace std; t ...
随机推荐
- 一个完整的TCP连接
当我们向服务器发送HTTP请求,获取数据.修改信息时,都需要建立TCP连接,包括三次握手,四次分手. 什么是TCP连接? 为实现数据的可靠传输,TCP要在应用进程间建立传输连接.它是在两个传输用户之间 ...
- js面向对象与原型
创建对象 var box = new Object();//创建对象 box.name = 'Lee'; //添加属性 box.age = 100; box.run = function(){ ret ...
- VPS搭建VPN、BLOG
FQ的正确姿势,你掌握了多少?老司机带你去墙外看看,来开车了坐稳! 购买VPS主机(服务端) 推荐性价比较高的VPS 搬瓦工https://bandwagonhost.com/ 上面的链接如果你打不开 ...
- Mobile Safari调用本地App, 否则进入App Store下载
需求: 如何让用户通过手机浏览器(Mobile Safari),访问一个URL就能直接打开ios上的App应用,如果该应用没有安装,那么直接跳转到App Store的App下载页面. 准备工作 ios ...
- 最好用的JQuery插件集合以及组合拳
[Tab页签] Jquery-tab [Table] mmGrid
- win7 cmd 操作mysql数据库
一 ,对MySql服务器的开启,重启,关闭等操作 当然,可以在win7的界面环境下,关闭或开启MySql服务.但是经常找不到win7的服务管理器,主要定位方法有二:命令行下输入servic ...
- 玩蛇记--Python处理海量手机号码
一.任务描述 上周,老板给我一个小任务:批量生成手机号码并去重.给了我一个Excel表,里面是中国移动各个地区的可用手机号码前7位(如下图),里面有十三张表,每个表里的电话号码前缀估计大概是八千个,需 ...
- 移动UI设计
移动应用UI设计模式 第二版 导航:跳板式,菜单式,选项卡式(微信)等 表单:登录表单,多步骤表单(递进式),计算表单,搜索表单,长表单等 表格:无表头表格,概览+数据型表格等 搜索:隐式搜索(滴滴打 ...
- 【JavaScript】Html form 提交表单方式
源:http://blog.csdn.net/wang02011/article/details/6299517 1.input[type='submit'] 2.input[type='image' ...
- jquery源码中的(function(window, undefined){})(window)【转】
(function( window, undefined ) {})(window);这个,为什么要将window和undefined作为参数传给它? (function( $, undefined ...