创建函数指针数组
这个技巧就是创建一个与回复类型一一对应的函数指针数组。在此之前,我们先看看怎么创建函数指针数组。如果想在数组中保存一组函数名,可以这样写:
replies[] = {dump, second_chance, marriage};
但这样的语法在 C 语言中行不通,如果想在数组中保存函数,就必须告诉编译器函数的具体特征:函数返回什么类型以及接收什么参数。也就是说必须使用下面这种复杂得多的语法:
如何用数组解决刚才的问题?
观察数组,函数名的顺序与枚举类型的顺序完全相同:enum response_type {DUMP, SECOND_CHANCE, MARRIAGE};
这点很重要,因为当 C 语言在创建枚举时会给每个符号分配一个从 0 开始的数字,所以 DUMP == 0, SECOND_CHANCE == 1 , 而 MARRIAGE == 2 ,也就是说可以通过 response_type 获取数 组中的函数指针。
能否用函数数组来修改之前的 main() 函数呢?
磨笔上阵
虽然这道题很难,但只要多花点时间应该没什么问题。补全这段代码所需的知识你都已经掌握了。在新版 main() 函数中,switch/case 语句已移除,你需要用一行代码来替代它,这行代码将从 replies 数组中找到对应的函数名,然后用它来调用函数。
磨笔上阵解答
这道题很难,新版 main() 函数中,switch/case 语句已移除,你需要用一行代码来替代它,这行代码将从 replies 数组中找到相应函数名,然后用它来调用函数。我们来分解这个表达式。
试驾
当运行新版程序时,得到了和刚才一样的输出:
区别呢?现在你用下面这行代码代替了整个 switch 语句:(replies[r[i].type])(r[i]);
如果需要在程序中多次调用回复函数,你不必复制很多代码,而当决定添加新的回复类型和函数时,只需要把它加到数组中即可:
函数指针数组让代码易于管理,它们让代码变得更短、更易于扩展,从而可以伸缩。一开始理解起来有些费劲,但函数指针数组的确可以提高 C 编程技巧。
要点
函数指针中保存了函数的地址。
函数名其实是函数指针。
11 并不完全等于,函数名是 L-value,在存储器中不分配变量。——译者注
如果你有函数
shoot() ,那么 shoot 和&shoot 都指向了 shoot() 函数。
可以用“返回类型(*变量名)(参数类型)”来声明新的函数指针。
如果 fp 是函数指针,那么可以用 fp (参数,……) 调用函数。
也可以用(*fp )(参数,……),两种情况都能工作。
C 标准库中有一个叫 qsort() 的排序函数。
qsort() 接收指向比较器函数的指针,比较器函数可以比较两个值的大小。
比较器函数接收两个指针,分别指向待排序数组中的两项。
如果把数据保存在数组中,就可以用函数指针数组将函数与数据项关联起来。
这里没有蠢问题问:为什么函数指针的语法这么复杂?答:因为当声明函数指针时,需要说明返回类型和参数类型,这就解释了为什么有那么多的括号。问:刚才那段代码看起来有点像其他语言中面向对象的代码,是吗?答:的确很像,面向对象语言将一组函数(称为方法)与数据关联在一起。同样你也可以用函数指针将函数与数据关联在一起。问:也就是说 C 语言也是面向对象的?太好了。答:C 语言不是面向对象语言,不过一些以 C 语言为基础的语言,例如 Objective-C 和 C++,在底层使用函数指针时创建了很多面向对象的特性。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论