《征服 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");  // 无论如何,*就是什么也没做
时间: 2024-10-26 02:14:14

《征服 C 指针》摘录4:函数 与 指针的相关文章

c指针 --笔记2返回指针值的函数

返回指针值的函数 一般带回指针值的函数,定义形式为: int *a (int x, int y); 看这个经典案例: #include <stdio.h> int main(int argc, char const *argv[]) { double score[][4] = {{60.0, 70.0, 80.5, 20.1}, {60.0, 70.0, 80.5, 21.1}, {60.0, 70.0, 80.5, 22.1}}; double *search(double(*pointer

数组指针、指针数组、函数指针、指针函数 -----笔记

1.数组的四种访问方式 定义数组 a[]; 指针 *p 指向数组a; (1) 利用数组的下表进行访问 a[i]; (2) 数组名+地址的偏移量i *(a+i) (3) 利用指针 p 进行下表访问 p[i] (4) 指针p + 地址的偏移量i *(p+i) 一维数组数组名:相当于一个单指针 2. 数组指针(指针)     指针数组(数组) 函数指针(指针)     指针函数(函数)    -------->只看后边两个字就能够区分是指针还是数组或函数 _______________________

函数和指针 C++

一.用函数指针变量调用函数. 指针变量也可以指向一个函数,一个函数在编译时被分配给一个入口地址.这个函数入口地址就称为函数的指针.可以用一个指针变量指向函数,然后通过该指针变量调用此函数. 定义指向函数的方法,格式是: int (*p)(int,int);     函数名代表函数入口地址,而max(a,b)则是函数调用. 二.返回指针值的函数 一个函数可以带回一个整数值.字符值.实型值等,也可以带回指针型的数据,即地址.其概念和以前类似,只是带回的值是指针类型而已.返回指针值的函数简称为指针函数

C语言中函数和指针的参数传递

最近写二叉树的数据结构实验,想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个例子讨论一下c语言中指针作为形参的函数中传递中隐藏的东西. 大家知道C++中有引用的概念,两个数据引用同一个数据,那么更改任意的一个都相当于更改了本体,那么另一个数据所对应的值也会改变,可是C中是没有这个概念的.所以就产生了一些东西.和我们本来想的有差别. 一.明确C语言中函数的入口: C语言中函数的形参负责接收外部数据,那么数据究竟怎么进入函数的呢,其实我们在函数体内操作的形参只是传递进来

函数指针,回调函数的定义和使用

一.函数指针 定义:函数指针是指向函数的指针变量,即本质是一个指针变量. int (*f) (int x); /* 声明一个函数指针 */ f=func; /* 将func函数的首地址赋给指针f */ 指向函数的指针包含了函数的地址,可以通过它来调用函数.声明格式如下:  类型说明符 (*函数名)(参数)其实这里不能称为函数名,应该叫做指针的变量名.这个特殊的指针指向一个返回整型值的函数.指针的声明笔削和它指向函数的声明保持一致.指针名和指针运算符外面的括号改变了默认的运算符优先级.如果没有圆括

十六、函数指针初级(函数指针与函数调用)

1.函数指针 ①函数在内存中也是有地址的.函数名代表函数的内存地址 ②函数指针是指向函数的指针变量 ③函数存放在代码区 ④函数指针定义与函数声明很相似 ⑤ 函数声明:int maxValue(int x , int y); 函数指针定义:int (*p)(int x , int y); ⑥函数指针剖析 int (*p)(int x , int y) 变量定义三部分: 类型:int (*)(int x , int y) 变量名:p 初值:NULL ⑦函数的地址已经固定了,但是指针变量的地址可以来回

契约型常量、函数指针、回调函数

契约性const对象的定义未使用const关键字,但被看做是一个const对象,例如: void ReadValue(const int& num) { cout << num; } int main(void) { int n = 0; ReadValue(n); //此时n被看作一个契约性常量 } 函数指针是指向函数的指针,声明如下: void (*funcp) (int x); void (*funcp) (int); //两种形式都可以 函数指针的小例子: //函数指针 #in

指针系统学习7-返回指针值的函数

1.返回指针值的函数 一个函数可以带回一个整型值.字符值.实型值等,也可以带回指针型的数据,即地址.其概念与以前类似,只是带回的值的类型是指针类型而已. 这种带回指针值的函数,一般定义形式为        类型名  *函数名(参数表列); 例如:   int *a(int x,int y); 例题:有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩.用指针函数来实现. #include <stdio.h> void main() { double sc

不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象, const 指针和指向 const 对象的指针, const 对象的引用

[源码下载] 不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象,  const 指针和指向 const 对象的指针, const 对象的引用 作者:webabcd 介绍不可或缺 Windows Native 之 C++ this 指针 对象数组 对象和指针 const 对象 const 指针和指向 const 对象的指针 const 对象的引用 示例1.CppEmployee 类CppEmployee.h #pragma