6.6.3 函数指针
类似于数组名是指向其首元素的指针,C 语言中,也可以将函数的名字看成是指向其所在内存位置的指针。因此,可以定义一个能保存函数内存地址的指针变量,并将其值初始化或赋值为某个函数的内存地址,而后可以通过这个指针进行函数的调用。
1.函数指针的定义
函数指针,即指向函数的指针。它的定义格式为:
返回值类型 (*变量名)(形参列表)
是不是和函数的定义格式非常相似?唯一不同的是,把原来函数名的地方换成了“(*变量名)”。即用一对小括号包含着星号和变量名。这里的星号也只是起标记作用,表明后面的变量名是一个指针类型的变量,即函数指针变量。需要注意的是,包含星号和变量名的小括号千万不要省略,否则就变成定义一个返回值是指针类型的函数了。
下面来定义一个函数指针吧,例如:
int (*pFunc)(int, int);
返回值类型为 int,形参列表中是两个 int,函数指针变量名为 pFunc。就像函数的声明一样,在定义函数指针时,只需要给出形参的类型即可,不需要指定形参的名字。
定义好函数指针后,并不能直接使用,还要让它指向一个函数,即让函数指针变量保存一个函数的内存地址,这就需要对函数指针进行初始化或者赋值了。
2.函数指针的初始化与赋值
定义函数指针变量 pFunc 后,就可以将一个函数的内存地址初始化或赋值给它。但这个函数必须符合函数指针的要求,即返回值和参数的类型必须与函数指针定义时所指定的返回值和参数类型一致。例如,函数指针变量 pFunc 只能存储返回值类型为 int、两个形参类型都为 int 的函数的内存地址,即函数指针 pFunc 只能指向返回值类型为 int、两个形参类型都为 int 的函数。因此,在对 pFunc 进行初始化或赋值之前,必须存在一个这样的函数,例如:
以上语句定义了一个 add 函数,它能实现两个整数相加的功能,有两个参数 a 和 b,都是 int 类型,函数的返回值也是 int 类型。
有了 add 函数,就可以定义函数指针,并对其进行初始化,例如:
int (*pFunc)(int, int) = add; //初始化
也可以采用赋值的方式:
int (*pFunc)(int, int); pFunc = add; //赋值
3.函数指针的使用
对函数指针 pFunc 进行初始化或赋值之后,就可以使用函数指针了,即通过函数指针 pFunc 来调用函数 add。
通过函数指针调用函数的格式为:
(*函数指针名)(实参列表);
在第一个小括号内,通过解引用运算符可以访问到函数指针所指向的函数,第二个小括号内是调用函数时所需传递的实参。例如:
(*pFunc)(10, 20);
通过对函数指针 pFunc 进行解引用,即可访问到 add 函数,然后将整数值 10 和 20 作为实参,进行 add 函数的调用。
甚至还可以将函数指针当成函数名来使用,即不需要对函数指针进行解引用,例如:
pFunc(10, 20);
4.函数指针作为函数参数
函数指针归根结底仍是指针的一种,因此,也可以将函数指针作为函数的参数。这样做的好处是:增加函数的灵活性,让函数在函数体代码不改变的情况下,能够根据函数指针所指向的函数的改变,展现出截然不同的效果。
下面对第 5 章中的例 5-4 进行扩展。
【 例 6-6 】编写程序,在数组中保存 1~100 的 10 个随机整数,要求根据用户的选择对数组元素进行升序或降序排序,并将排序后的数组元素打印输出。
先定义两个函数 asc 和 desc:
这两个函数都具有 int 类型的返回值和两个 int 类型的参数。asc 函数的功能是判断参数 a 是否大于参数 b,如果成立则返回真,否则返回假。而 desc 函数正好相反,当参数 a 小于参数 b 时返回真,否则返回假。
在冒泡排序中,相邻两元素进行比较,如果是升序排序方式,若前一个元素大于后一个元素,则需进行交换,因此,asc 函数是升序排序时所需要的。如果是降序排序方式,若前一个元素小于后一个元素,则需进行交换,因此,desc 函数是降序排序时所需要的。
接下来,我们对冒泡排序的 bubble 函数进行修改,添加一个函数指针类型的参数 pFunc:
void bubble(int a[], int len, int (*pFunc)(int, int))
并将双层 for 循环内的 if 语句条件表达式修改为:
if(pFunc(a[j], a[j + 1]))
通过函数指针来调用它所指向的函数,即调用 asc 函数或者是 desc 函数。
最后修改一下主函数,添加用户对排序方式的选择。
整个程序的代码如下:
当用户选择 1 时,表示按照升序方式对数组元素进行排序,所以将函数名 asc 作为 bubble 函数的第 3 个参数进行传递,即让 pFunc 指向 asc 函数。在两两元素进行比较时,若前一个元素大于后一个元素则进行交换,从而使数组元素呈现递增的排序状态。程序执行效果如下:
1.ascending order 2.descending order Please choose: 1 10 24 42 47 64 66 69 71 72 93
当用户选择 2 时,表示按照降序方式对数组元素进行排序,所以会将函数名 desc 作为 bubble 函数的第 3 个参数进行传递,即让 pFunc 指向 desc 函数。在两两元素进行比较时,若前一个元素小于后一个元素则进行交换,从而使数组元素呈现递减的排序状态。程序执行效果如下:
1.ascending order 2.descending order Please choose: 2 71 67 62 62 60 51 47 33 28 23
当用户选择 1 和 2 之外的数字时,程序会提示用户输入数字错误,并不会对数组元素进行排序,而直接打印出数组各元素。程序执行效果如下:
1.ascending order 2.descending order Please choose: 3 Wrong number entered. 27 25 66 8 37 92 39 62 56 55
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论