深入理解指针函数

发布者:SecretWhisper最新更新时间:2015-10-23 来源: eefocus关键字:指针函数 手机看文章 扫描二维码
随时随地手机看文章
1.指针函数的定义
    顾名思义,指针函数即返回指针的函数。其一般定义形式如下:
 
       类型名 *函数名(函数参数表列);
 
    其中,后缀运算符括号“()”表示这是一个函数,其前缀运算符星号“*”表示此函数为指针型函数,其函数值为指针,即它带回来的值的类型为指针,当调用这个函数后,将得到一个“指向返回值为…的指针(地址),“类型名”表示函数返回的指针指向的类型”。
 
    “(函数参数表列)”中的括号为函数调用运算符,在调用语句中,即使函数不带参数,其参数表的一对括号也不能省略。其示例如下:
 
    int *pfun(int, int);
 
    由于“*”的优先级低于“()”的优先级,因而pfun首先和后面的“()”结合,也就意味着,pfun是一个函数。即:
 
    int *(pfun(int, int));
 
    接着再和前面的“*”结合,说明这个函数的返回值是一个指针。由于前面还有一个int,也就是说,pfun是一个返回值为整型指针的函数。
 
    我们不妨来再看一看,指针函数与函数指针有什么区别?
 
    int (*pfun)(int, int);
 
    通过括号强行将pfun首先与“*”结合,也就意味着,pfun是一个指针,接着与后面的“()”结合,说明该指针指向的是一个函数,然后再与前面的int结合,也就是说,该函数的返回值是int。由此可见,pfun是一个指向返回值为int的函数的指针。
 
    虽然它们只有一个括号的差别,但是表示的意义却截然不同。函数指针的本身是一个指针,指针指向的是一个函数。指针函数的本身是一个函数,其函数的返回值是一个指针。
 
2.    用函数指针作为函数的返回值
    在上面提到的指针函数里面,有这样一类函数,它们也返回指针型数据(地址),但是这个指针不是指向int、char之类的基本类型,而是指向函数。对于初学者,别说写出这样的函数声明,就是看到这样的写法也是一头雾水。比如,下面的语句:
 
    int (*ff(int))(int *, int);
 
我们用上面介绍的方法分析一下,ff首先与后面的“()”结合,即:
 
    int (*(ff(int)))(int *, int);                            // 用括号将ff(int)再括起来
 
也就意味着,ff是一个函数。
 
    接着与前面的“*”结合,说明ff函数的返回值是一个指针。然后再与后面的“()”结合,也就是说,该指针指向的是一个函数。
 
这种写法确实让人非常难懂,以至于一些初学者产生误解,认为写出别人看不懂的代码才能显示自己水平高。而事实上恰好相反,能否写出通俗易懂的代码是衡量程序员是否优秀的标准。一般来说,用typedef关键字会使该声明更简单易懂。在前面我们已经见过:
 
    int (*PF)(int *, int);
 
也就是说,PF是一个函数指针“变量”。当使用typedef声明后,则PF就成为了一个函数指针“类型”,即:
 
    typedef int (*PF)(int *, int);
 
这样就定义了返回值的类型。然后,再用PF作为返回值来声明函数:
 
    PF ff(int);
 
   下面将以程序清单1为例,说明用函数指针作为函数的返回值的用法。当程序接收用户输入时,如果用户输入d,则求数组的最大值,如果输入x,则求数组的最小值,如果输入p,则求数组的平均值。
 
程序清单 1  求最值与平均值示例
 
1       #include
 
2       #include
 
3       double GetMin(double *dbData, int iSize)               // 求最小值
 
4       {
 
5           double dbMin;
 
6           int i;
 
7      
 
8           assert(iSize>0);
 
9           dbMin=dbData[0];
 
10          for (i=1; i
 
11                if (dbMin>dbData[i]) {
 
12                     dbMin=dbData[i];
 
13                }
 
14          }
 
15          return dbMin;
 
16     }
 
17
 
18     double GetMax(double *dbData, int iSize)                 // 求最大值
 
19     {
 
20         double dbMax;
 
21         int i;
 
22
 
23         assert(iSize>0);
 
24         dbMax=dbData[0];
 
25         for (i=1; i
 
26             if (dbMax< dbData[i]) {
 
27                 dbMax=dbData[i];
 
28             }
 
29         }
 
30         return dbMax;
 
31     }
 
32
 
33     double GetAverage(double *dbData, int iSize)            // 求平均值
 
34     {
 
35         double dbSum=0;
 
36         int i;
 
37    
 
38         assert(iSize>0);
 
39         for (i=0; i
 
40         {
 
41              dbSum+=dbData[i];
 
42         }
 
43         return dbSum/iSize;
 
44     }
 
45
 
46     double UnKnown(double *dbData, int iSize)             // 未知算法
 
47     {
 
48         return 0;
 
49     }
 
50
 
51     typedef double (*PF)(double *dbData, int iSize);     // 定义函数指针类型
 
52     PF GetOperation(char c)                              // 根据字符得到操作类型,返回函数指针
 
53     {
 
54         switch (c)
 
55         {
 
56           case 'd':
 
57                     return GetMax;
 
58           case 'x':
 
59                     return GetMin;
 
60           case 'p':
 
61                     return GetAverage;
 
62           default:
 
63                     return UnKnown;
 
64           }
 
65     }
 
66
 
67     int main(void)
 
68     {
 
69          double dbData[]={3.1415926, 1.4142, -0.5,999, -313, 365};
 
70          int iSize=sizeof(dbData)/sizeof(dbData[0]);
 
71          char c;
 
72
 
73          printf("Please input the Operation :n");
 
74          c=getchar();
 
75          printf("result is %lfn", GetOperation(c)(dbData,iSize));   // 通过函数指针调用函数
 
76    }
 
    上述程序中前面4个函数分别实现求最大值、最小值、平均值和未知算法,然后实现了GetOperation函数。这个函数根据字符的返回值实现上面4个函数。它是以函数指针的形式返回的,从后面的main函数的GetOperation(c)(dbData, iSize)可以看出,通过这个指针可以调用函数。
关键字:指针函数 引用地址:深入理解指针函数

上一篇:单片机c语言指针和取地址以及类型转换
下一篇:深入理解typedef

推荐阅读最新更新时间:2024-03-16 14:37

C51中的函数指针
概述 函数指针是C编程语言众多难懂的特性之一。由于C编译器对关于8051架构的独特要求,函数指针和可重入函数需要克服更大的挑战。这主要是因为函数参数传递的方式。 通常,(对于大多数非8051的芯片),函数参数是在栈上以压入和弹出的汇编指令来完成。由于8051的栈大小有限(仅128字节,某些设备上更低至64字节),函数参数传递必须用不同的技术来传递。 英特尔为8051推出PL/ML-51编译器时,他们引入了将参数存储在固定内存位置的技术。当链接器被调用时,它会建立程序的调用树,找出哪些函数参数是相互独立的,然后覆盖它们。这就是链接器OVERLAY指令的开始。 由于PL/M-51不支持函数指针,所以从未出现间接函数调用的问
[单片机]
第53节:指针让一个函数可以封装多个参数
开场白: 当我们想把某种算法通过一个函数来实现的时候,如果不会指针,那么只有两种方法。 第1种:用不带参数返回的空函数。这是最原始的做法,也是我当年刚毕业就开始做项目的时候经常用的方法。它完全依靠全局变量作为函数的输入和输出口。我们要用到这个函数,就要把参与运算的变量直接赋给对应的输入全局变量,调用一次函数之后,再找到对应的输出变量,这些输出变量就是我们要的结果。这种方法的缺点是阅读不直观,封装性不强,没有面对用户的输入输出接口。 第2种:用return返回参数和带输入形参的函数,这种方法已经具备了完整的输入和输出性能,比第1种方法直观多了。但是这种方法有它的局限性,因为return只能返回一个变量,如果要用在返回多个输出结果的
[单片机]
STM32-使用函数指针时莫名复位问题原因
程序莫名复位,经检查是如下原因引起,访问了未知的空间! 这个1不应该加,改正后就没有复位了,所以在编程和测试中,一定要注意边界条件。
[单片机]
STM32-使用<font color='red'>函数</font><font color='red'>指针</font>时莫名复位问题原因
关于指针函数的范例
关于指针函数的范例 #define ubyte unsigned char #define uint unsigned int #define ulong unsigned long ubyte kbCode; // 按键编码纪录 ubyte kbStatus; // 键盘当前状态,可以理解为菜单层次 // 按键的四种不同工作状态对应的函数指针对照表,每三字节对应一个按键 // 每一项包含三个字节,分别代表按键码,键盘状态,对应处理程序编号 // 本表对应于日常操作,不是修改状态 ubyte code TAB0 ={ 0x11,0x00,0x01, // 按键'
[单片机]
C51里的函数指针
在C语言里面提供了函数指针,我认为它比较重要的功能就是用来提供接口,使得C语言可以模拟面向对象的语言为某些功能提供接口,实现功能代码的隔离。 这不,前些日子写了个小程序,用C51写的,其中有个功能就是操作液晶屏,在上面显示菜单、输出结果什么的。在我看来,这部分功能使用函数指针最好不过了。譬如,不管是什么菜单,总得要显示出来吧,定义一个show()接口就好。这样上层代码很简单,反正对每个菜单都调用其show()接口,它们自己完成显示。 嗯,可是想法是好的,结果是不妙的。首先这么做在C51的语法层面上没有任何问题,编译后没有任何错误。可是实际运行时就发现一些奇怪的现象,譬如调用某个函数,明明入口参数的值是100,跑到函数内部就
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved