9.5 函数指针和返回指针值的函数
9.5.1 用函数指针变量调用函数
以往学习过,指针变量可以指向整型变量、字符串、数组,现在学习一下指针变量指向函数,这也是一个很重要的话题,是一些比较有技巧的程序代码中常用的编程手法,请认真学习。
函数,前面章节已经学习过,是一段代码,可以被调用,所以,首先看看如下范例,演示一个普通的函数调用范例——求最大值:
现在需要知道,这个函数max因为有它要执行的功能(比较大小,返回两个值中较大的值),所以会占用一段内存(函数中的代码是要占用内存的),实际上每个函数都会占用一段内存,因此有一个起始地址,可以用一个指针变量指向一个函数(实际就是指向函数的起始地址),从而可以通过指针变量来调用所指向的函数。
改造一下上面的代码:
执行后,得到了和普通函数调用范例相同的结果,那么在应用函数指针这个范例中,一定要注意函数指针的定义方法,如果上面的函数指针变量的定义写成了如下这样:
则因为“()”优先级高于“*”,那这就变成函数说明了:int *表示这个函数的返回值是指向整型变量的指针,那和开发者的本意就天差地别了。
还有一个很重要的问题,设置一下断点,观察一下p的值和max的值,如图9.26所示。注意到了一个重要问题:语句“p=max;”执行后,为什么max和p两者值不相等?
图9.26 函数入口地址赋值给函数指针后的值比较,两个值并不相同
Visual Studio等开发环境有一些内部处理手段:把max等许多这种函数的入口地址保存到一张表格中,函数调用的时候系统会到这张表格里取真实的函数入口地址然后再调用函数,所以看到max和p值不同。p里面保存(指向)的是真正的函数入口地址,max里存的是表格里面一个对应关系地址,通过max这里的地址可以找到真正的函数入口地址。
不过,如果用printf语句输出,即使是输出max,也能输出真实的函数入口地址,例如如下两行得到的结果一样,看起来这确实有点奇怪,但知道就好:
总结一下:
(1)函数指针变量定义的一般形式。
其中,“数据类型标识符”是指函数的返回值类型;“形参列表”里可以只有类型说明符(不必带有形参名),多个类型说明符之间用逗号分隔。
在代码中,只要满足“数据类型标识符”,也满足“形参列表”的函数,其地址(函数名)都可以赋给该函数指针,哪个函数地址赋给了这个函数指针,这个函数指针就指向哪个函数,所以,可以通过该函数指针指向不同的函数来达到调用不同函数的目的,这是有实际用途的。以后随着读者写的代码以及看的代码渐渐的多起来,可能会看到这种程序写法。
(2)函数的调用,可以通过函数名调用,也可以通过函数指针调用。
(3)对指向函数的指针变量p,做一些像p++、p--、p+n(n代表一个数字)等运算都不可以,也没有意义。