周立功手把手教你学嵌入式编程:函数指针与指针函数的应用
比如,pf(5, 8),(*pf)(5, 8)。为何pf与(*pf)等价呢?
● 一种说法是,由于pf是函数指针,假设pf指向add()函数,则*pf就是函数add,因此使用(*pf)()调用函数。虽然这种格式不好看,但它给出了强有力的提示——代码正在使用函数指针调用函数。
● 另一种说法是,由于函数名是指向函数的指针,那么指向函数的指针的行为应该与函数名相似,因此使用pf()调用函数。因为这种调用方式既简单又优雅,所以人们更愿意选择——说明人类追随美好感受的内心是无法抗拒的。
虽然它们在逻辑上互相冲突,但不同的流派有不同的观点,且容忍逻辑上无法自圆其说的观点,正是人类思维活动的特点。
在一个袖珍计算器中,经常需要用到加减乘除开方等各种各样的计算,虽然其调用方法都是一样,但在运行中需要根据具体情况决定选择调用支持某一算法的函数。如果使用如图 2.1(a)所示的直接调用方式,则势必形成了依赖关系结构,策略会受到细节改变的影响,当使用如图 2.1(b)所示的函数指针接口倒置(或反转)了这种依赖关系结构时,则使得细节和策略都依赖于函数指针接口,断开了不想要的直接依赖。
当将直接访问抽象成函数指针倒置(或反转)了依赖的关系时,高层模块不再依赖于低层模块。高层模块依赖于抽象,即一个函数指针形式的接口,同时细节也依赖于抽象,pf()实现了这个接口,即两者都依赖于函数指针接口。在C语言中,通常用函数指针来实现DIP(倒置依赖关系),断开不想要的直接依赖。既可以通过函数指针调用服务(被调用代码),服务也可以通过函数指针回调用户函数。都是一样,但在运行中需要根据具体情况决定选择调用支持某一算法的函数。如果使用如图 2.1(a)所示的直接调用方式,则势必形成了依赖关系结构,策略会受到细节改变的影响,当使用如图 2.1(b)所示的函数指针接口倒置(或反转)了这种依赖关系结构时,则使得细节和策略都依赖于函数指针接口,断开了不想要的直接依赖。

图 2.1 使用函数指针倒置依赖关系
函数指针是程序员经常忽视的一个强大的语言能力,不仅使代码更灵活可测,而且对消除重复条件逻辑有很大的帮助,同时还可以使调用者免于在编译时或链接时依赖于某个特定的函数,其极大地好处是减少了C语言模块之间的耦合。但函数指针的使用是有条件的,如果主调函数与被调函数之间的调用关系永远不会发生改变,则采用直接调用方式是最简单的,在这种情况下,模块之间耦合是合理的,不仅代码简单直截了当,而且开销也是最小的。如果需要在运行时使用一个或多个函数指针调用某一函数,则使用函数指针是最佳的选择,通常将其称之为动态接口,其范例程序详见程序清单 2.1。
程序清单 2.1 通过函数指针调用函数范例程序(1)
1 #include
2 int add(int a, int b)
3 {
4 printf("addition function\n");
5 return a + b;
6 }
7
8 int sub(int a, int b)
9 {
10 printf("subtration function\n");
11 return a - b;
12 }
13
14 int main(void)
15 {
16 int (*pf)(int, int);
17
18 pf = add;
19 printf("addition result:%d\n", pf(5, 8));
20 pf = sub;
21 printf("subtration result:%d\n", pf(8, 5));
22 return 0;
23 }
由于任何数据类型的指针都可以给void指针变量赋值,且函数指针的本质就是一个地址,因此可以利用这
函数指针 指针函数 数据结构 ametal 程序设计 相关文章:
- 周立功教你学C语言编程与程序设计:这样写函数指针数组最好用(07-31)
- 周立功“程序设计与数据结构”:深度解剖动态分布内存的free()函数与realloc()函数(07-25)
- 周立功《程序设计与数据结构》:字符串函数(08-05)
- 嵌入式如何进一步成长,该学习哪些书呢?(08-13)
- 不完全类型和抽象数据类型的定义(08-14)
- 怎么像整数一样计算字符?(08-14)
