周立功手把手教你学嵌入式编程:函数指针与指针函数的应用
周立功教授数年之心血之作《程序设计与数据结构》以及《面向AMetal框架与接口的编程(上)》。书本内容公开后,在电子行业掀起一片学习热潮。经周立功教授授权,本公众号特对《程序设计与数据结构》一书内容进行连载,愿共勉之。
第二章为程序设计技术,本文为2.1.1 函数指针和2.1.2指针函数。
>>>> 2.1 函数指针与指针函数
>>> 2.1.1 函数指针
变量的指针指向的是一块数据,指针指向不同的变量,则取到的是不同的数据。而经过编译后的函数都是一段代码,系统随即为相应的代码分配一段存储空间,而存储这段代码的起始地址(又称为入口地址)就是这个函数的指针,即跳转到某一个地址单元的代码处去执行。函数指针指向的是一段代码(即函数),指针指向不同的函数,则具有不同的行为。
因为函数名是一个常量地址,所以只要将函数的地址赋给函数指针即可调用相应的函数。如同数组名一样,我们用的是函数本身的名字,它会返回函数的地址。当一个函数名出现在表达式中时,编译器就会将其转换为一个指针,即类似于数组变量名的行为,隐式地取出了它的地址。即函数名直接对应于函数生成的指令代码在内存中的地址,因此函数名可以直接赋值给指向函数的指针。既然函数指针的值可以改变,那么就可以使用同一个函数指针指向不同的函数。如果有以下定义:
int (*pf)(int); // pf函数指针的类型是什么?
C语言的发明者K&R是这样解释的,"因为*是前置运算符,它的优先级低于(),为了让连接正确地进行,有必要加上括号。"这未免有些牵强附会了,解释来解释去反而将人搞晕了。因为声明中的*、()、[]都不是运算符,而运算符的优先顺序在语法规则中是在其它地方定义的。其详解如下:
int (*pf)(int a); // pf是指向…的指针
int (*pf)(int a); // pf是指向…的函数(参数为int)的指针
int (*pf)(int a); // pf是指向返回int的函数(参数为int)的指针
即pf是一个指向返回int的函数的指针,它所指向的函数接受一个int类型的参数。 "int (*)(int)"类型名被解释为指向返回int函数(参数为int)的指针类型。如果在该定义前添加typedef,比如:
typedef int (*pf)(int a);
未添加typedef前,pf是一个函数指针变量;而添加typedef后,pf就变成了函数指针类型,习惯的写法是类型名pf大写为PF。比如:
typedef int (*PF)(int a);
与其它类型的声明不同,函数指针的声明要求使用typedef关键字。另外,函数指针的声明与函数原型的唯一不同是函数名用(*PF)代替了,"*"在此处表示"指向类型名为PF的函数"。显然,有了PF类型即可定义函数指针变量pf1、pf2。比如:
PF pf1, pf2;
虽然此声明等价于:
int (*pf1)(int a);
int (*pf2)(int a);
但这种写法更难理解。既然函数指针变量是一个变量,那么它的值就是可以改变的,因此可以使用同一个函数指针变量指向不同的函数。使用函数指针必须完成以下工作:
● 获取函数的地址,比如,pf = add,pf = sub;
● 声明一个函数指针,比如,"int (*pf)(int, int);";
● 使用函数指针来调用函数,
函数指针 指针函数 数据结构 ametal 程序设计 相关文章:
- 周立功教你学C语言编程与程序设计:这样写函数指针数组最好用(07-31)
- 周立功“程序设计与数据结构”:深度解剖动态分布内存的free()函数与realloc()函数(07-25)
- 周立功《程序设计与数据结构》:字符串函数(08-05)
- 嵌入式如何进一步成长,该学习哪些书呢?(08-13)
- 不完全类型和抽象数据类型的定义(08-14)
- 怎么像整数一样计算字符?(08-14)