a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 90|回复: 1

[程序员] 2012年软件水平考试程序员辅导笔记之浅析函数指针

[复制链接]
发表于 2012-8-2 08:51:15 | 显示全部楼层 |阅读模式
  函数指针的概念是指向函数的指针变量。 因而“函数指针”自己首先应是指针变量,只不外该指针变量指向函数。在大大都情形下我们使用不到,也忽略了它的存在。函数名现实上也是一种指针,指向函数的进口地址,但它又分歧于通俗的如int*、double*指针,看下面的例子来理解函数指针的概念:
; @5 ]3 H. M; |& S2 r  view plain int function( int x, int y );int main ( void ) " S8 v" X% w) K/ a' W( M( ~% ^
  { int (*fun) ( int x, int y );int a = 10, b = 20;function( a, b );fun = function;(*fun)( a, b );……
# b9 B8 O" z! d, N! e+ F  }第一行代码首先界说了一个函数function,其输酬报两个整型数,返回也为一个整型数(输入参数和返回值可为其它任何数据类型);后面又界说了一个函数指针fun,与int*或double*界说指针分歧的是,函数指针的界说必需同时指出输入参数,剖明这是一个函数指针,而且*fun也必需用一对括号括起来;并将函数指针赋值为函数function,前提前提是*fun和function的输入参数和返回值必需连结一致,否则无法经由过程编译。可以直接挪用函数function(),也可以直接挪用函数指针,二者是等效的。 9 H7 _5 Y# P8 u; M0 F' A% p  K
  声明函数指针   s" s% u( Z$ ?" ^+ Z  C
  回调函数是一个轨范员不能显式挪用的函数;经由过程将回调函数的地址传给挪用者从而实现挪用。要实现回调,必需首先界说函数指针。尽管界说的语法有点不成思议,但如不美观你熟悉函数声明的一般体例,便会发现函数指针的声明与函数声明很是近似。请看下面的例子: 2 Y% f2 R  c  n2 g8 J* f
  void f(); // 函数原型 6 g5 _1 M$ n$ C, f
  膳缦沔的语句声了然一个函数,没有输入参数并返回void.那么函数指针的声明体例如下:
6 x+ a, \: W. z0 X" t  void (*) ();
+ Z6 i* W$ |; T7 R* T% S6 Q  函数存放在内存的代码区域内,它们同样有地址,我们若何能获得函数的地址呢?
1 s+ u5 }4 A1 T2 Q  @# E  如不美观我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的肇端地址。 5 T. j  e2 G2 i. b0 V7 ?; |( H
  界说一个指向函数的指针用如下的形式,以膳缦沔的test()为例: , e5 O& `4 s+ u" @
  int (*fp)(int a); //这里就界说了一个指向函数的指针
5 i+ x4 O0 j" \; Y9 g  函数指针绝对不能指向分歧类型,或者是带分歧形参的函数,在界说函数指针的时辰我们很轻易犯如下的错误。 4 n0 f' ]7 r6 l$ x2 f' M
  int *fp(int a); //这里是错误的,因为按照连系性和优先级来看就是先和()连系,然后酿成了一个返回整形指针的函数了,而不是函数指针,这一点尤其需要注重!
+ V( S2 k2 l) C+ t) r, H; X9 w  例如函数原型为: $ K7 F; ]+ y1 z* u7 |( N+ {
  int fun(int *, int);   f1 x8 ?0 q# y* U4 y
  则函数指针可以声明为: int (*pf)(int *, int);
回复

使用道具 举报

 楼主| 发表于 2012-8-2 08:51:16 | 显示全部楼层

2012年软件水平考试程序员辅导笔记之浅析函数指针

  当然从上述例子看不出函数指针的利益,目的主若是想引出函数指针数组的概念。我们从膳缦沔例子可以得知,既然函数名可以经由过程函数指针加以保留,那们也必然能界说一个数组保留若干个函数名,这就是函数指针数组。正确使用函数指针数组的前提前提是,这若干个需要经由过程函数指针数组保留的函数必需有不异的输入、输出值。 4 x; l5 A7 A( m3 a
  view plain //首先界说256个措置函数(及其实现)。
2 X+ v$ \8 `9 X. }$ b  int function0( int *, int );…… # ^3 e" H1 g4 P3 ~: o: s" R
  int function255( int *, int ); 1 M' C! ]5 a$ q+ N% f
  //其次界说函数指针数组,并给数组赋值。
4 U5 t. R( Y4 g& e/ V+ e  void (*fun[256])( int *, int ); 2 A0 R1 r5 @; ^& y% f( w
  fun[0] = function0;……
) ?% g& U- h0 c  fun[255] = function255;
. ~% d, k/ b2 v8 q  \' Z  如不美观赋了分歧的值给函数指针,那么挪用者将挪用分歧地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。
, X3 U' ?$ ]  c+ m6 s% Y5 N  下面我们来看一个具体的例子:
$ b8 j% [; o6 e2 B  view plain int test(int a)
4 z3 v- K7 `  C* q: X8 h, o  { return a;} $ |$ ]- Z! e+ r+ E1 H& P3 V
  int main(void)
' u! Z" T% o* e5 I  { int (*fp)(int a);fp = test; //将函数test的地址赋给函数指针fp cout《fp(5)《“|”《(*fp)(10)《endl; //输出fp(5),这是尺度c++的写法,(*fp)(10)这是兼容c说话的尺度写法,两种赞成,但注重区分,避免写的轨范发生移植性问题!
* y4 Z6 S3 [" x8 B+ r1 n) G  return 0;} typedef界说可以简化函数指针的界说,在界说一个的时辰感受不出来,但界说多了就知道便利了,膳缦沔的代码改写成如下的形式: ' e2 U  G/ a2 E8 c) h; z
  view plain int test(int a)
6 @' j2 R& d- M  { return a;}
5 k" o- L$ R# z( X5 H' e8 w  int main(void)
1 Z7 j% ^* l8 X) l1 {4 r" m/ l  { typedef int (*fp)(int a); //注重,这里不是生命函数指针,而是界说一个函数指针的类型,这个类型是自己界说的,类型名为fp fp fpi; //这里操作自己界说的类型名fp界说了一个fpi的函数指针! 5 j8 k0 [$ e& N% z
  fpi = test;cout《fpi(5)《“|”《(*fpi)(10)《endl; //输出fp(5),这是尺度c++的写法,(*fp)(10)这是兼容c说话的尺度写法,两种赞成,但注重区分,避免写的轨范发生移植性问题!   return 0;}
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-18 13:49 , Processed in 0.298320 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表