周立功:指针函数的应用到底有多广泛呢?

-回复 -浏览
楼主 2021-03-29 07:24:53
举报 只看此人 收藏本贴 楼主


近日周立功教授公开了数年的心血之作《程序设计与数据结构》,电子版已无偿性分享到电子工程师与高校群体下载,经周立功教授授权,特对本书内容进行连载。


>>>> 1.1 函数指针与指针函数


>>> 1.1.1 函数指针 


>>> 1.1.2 指针函数 


实际上,指针变量的用途非常广泛,指针不仅可以作为函数的参数,而且指针还可以作为函数的返回值。当函数的返回值是指针时,则这个函数就是指针函数。当给定指向两个整数的指针时,如程序清单 2.2所示的函数返回指向两个整数中较大数的指针。当调用max时,用指向两个int类型变量的指针作为参数,且将结果存储在一个指针变量中,其中,max函数返回的指针是作为实参传入的两个指针的一个。


程序清单 2.2 求最大值函数(指针作为函数的返回值)


1     #include<stdio.h>

2     int *max(int *p1, int *p2)

3     {

4            if(*p1 > *p2)

5                   return p1;

6            else

7                   return p2; 

8     }

9

10   int main(int argc, char *argv[])

11   { 

12          int *p, a, b;

13          a = 1;  b = 2;

14          p = max(&a, &b);

15          printf("%d\n", *p);

16          return 0;

17   }


当然,函数也可以返回字符串,它返回的实际是字符串的地址,但一定要注意如何返回合法的地址。既可以返回是静态的字符串地址,也可以在堆上分配字符串的内存,然后返回其地址。注意,不要返回局部字符串的地址,因为内存有可能被别的栈帧覆写。


下面我们再来看一看,指针函数与函数指针变量有什么区别?如果有以下定义:


int *pf(int *, int);                          // int *(int *, int)类型

int (*pf)(int, int);                        // int (*)(int, int)类型


虽然两者之间只差一个括号但表示的意义却截然不同。函数指针变量的本质是一个指针变量其指向的是一个函数指针函数的本质是一个函数即将pf声明为一个函数它接受2个参数其中一个是int *另一个是int其返回值是一个int类型的指针。


在指针函数中,还有一类这样的函数,其返回值是指向函数的指针。对于初学者,别说写出这样的函数声明,就是看到这样的写法也是一头雾水。比如,下面这样的语句:


int (* ff (int))(int, int);                            // ff是一个函数

int (* ff (int))(int, int);                          // ff是一个指针函数,其返回值是指针

int (* ff (int))(int, int);                        // 指针指向的是一个函数


这种写法确实让人非常难懂,以至于一些初学者产生误解,认为写出别人看不懂的代码才能显示自己水平高。而事实上恰好相反,能否写出通俗易懂的代码是衡量程序员是否优秀的标准。当使用typedef后,则PF就成为了一个函数指针类型。即:


typedef int (*PF)(int, int);


有了这个类型,那么上述函数的声明就变得简单多了。即:


       PF ff(int);


下面将以程序清单 2.3为例,说明用函数指针作为函数返回值的用法。当用户分别输入d、x和p时,求数组的最大值、最小值和平均值。


程序清单 2.3  求最值与平均值范例程序


1     #include<stdio.h>

2     #include <assert.h>

3     double getMin(double *dbData, int iSize)             // 求最小值

4     {

5            double dbMin; 

6

7            assert((dbData != NULL) && (iSize > 0));

8            dbMin = dbData[0]; 

9            for (int i = 1; i < iSize; i++){ 

10                 if (dbMin > dbData[i]){

11                        dbMin = dbData[i];

12                 }

13          }

14          return dbMin;

15   }

16

17   double getMax(double *dbData, int iSize)                // 求最大值

18   {

19          double dbMax;

20

21          assert((dbData != NULL) && (iSize > 0)); 

22          dbMax = dbData[0]; 

23          for (int i = 1; i < iSize; i++){

24                 if (dbMax < dbData[i]){ 

25                        dbMax = dbData[i];

26                 }

27          }

28          return dbMax;

29   }

30

31   double getAverage(double *dbData, int iSize)          // 求平均值

32   {

33          double dbSum = 0;

34

35          assert((dbData != NULL) && (iSize > 0)); 

36          for (int i = 0; i < iSize; i++){

37                 dbSum += dbData[i]; 

38          }

39          return dbSum/iSize;

40   } 

41

42   double unKnown(double *dbData, int iSize)            // 未知算法

43   { 

44          return 0;

45   }

46

47   typede double (*PF)(double *dbData, int iSize);          // 定义函数指针类型

48   PF getOperation(char c)                                   // 根据字符得到操作类型,返回函数指针

49   {

50          switch (c){ 

51          case 'd':

52                 return getMax; 

53          case 'x': 

54                 return getMin; 

55          case 'p': 

56                 return getAverage;

57          default:

58                 return unKnown;       

59          }

60   } 

61

62   int main(void) 

63   {

64          double dbData[] = {3.1415926, 1.4142, -0.5, 999, -313, 365}; 

65          int iSize = sizeof(dbData) / sizeof(dbData[0]); 

66          char c; 

67

68          printf("Please input the Operation :\n");

69          c = getchar(); 

70          PF pf = getOperation(c);

71          printf("result is %lf\n", pf(dbData, iSize));

72          return 0;

73   }


前4个函数分别实现了求最大值、最小值、平均值和未知算法,getOperation()根据输入字符得到的返回值是以函数指针的形式返回的,从pf(dbData, iSize)可以看出是通过这个指针调用函数的。注意,指针函数可以返回新的内存地址、全局变量的地址和静态变量的地址,但不能返回局部变量的地址,因为函数结束后,在函数内部的声明的局部变量的声明周期已经结束,内存将自动放弃。显然,在主调函数中访问这个指针所指向的数据,将会产生不可预料的结果。



 往期好文推荐 

周立功:函数指针的无穷威力,你知道吗?

周立功:动态分布内存——free()函数与realloc()函数

广州周立功单片机科技有限公司

电话:4008882705
官网:www.zlgmcu.com
邮箱:zlg.sales@zlgmcu.com


我要推荐
转发到

友情链接