a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 104|回复: 0

[程序员] 2012年软件水平初级资格程序员考试重点知识5

[复制链接]
发表于 2012-8-2 08:51:15 | 显示全部楼层 |阅读模式
函数指针的概念是指向函数的指针变量。 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。在大多数情况下我们使用不到,也忽略了它的存在。函数名实际上也是一种指针,指向函数的入口地址,但它又不同于普通的如int*、double*指针,看下面的例子来理解函数指针的概念: * g& e( g6 C7 c9 ~; Q: p: U
  view plain int function( int x, int y );int main ( void )
# t5 B% k- E$ g% _1 i0 @* f' V4 `  { int (*fun) ( int x, int y );int a = 10, b = 20;function( a, b );fun = function;(*fun)( a, b );……
, d6 Y3 \+ {8 R7 q  }第一行代码首先定义了一个函数function,其输入为两个整型数,返回也为一个整型数(输入参数和返回值可为其它任何数据类型);后面又定义了一个函数指针fun,与int*或double*定义指针不同的是,函数指针的定义必须同时指出输入参数,表明这是一个函数指针,并且*fun也必须用一对括号括起来;并将函数指针赋值为函数function,前提条件是*fun和function的输入参数和返回值必须保持一致,否则无法通过编译。可以直接调用函数function(),也可以直接调用函数指针,二者是等效的。 ; H: s2 X# c% n# J# |: g* |
  声明函数指针
9 ^- }! k) ]% H' Q/ v' ^/ s  回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。请看下面的例子: 1 Z  V3 S' y& }" O, r. G
  void f(); // 函数原型
* a) _; Z  c4 ~: }  K3 D( C  上面的语句声明了一个函数,没有输入参数并返回void.那么函数指针的声明方法如下: 0 d% }- ^' M( X8 j2 m, l
  void (*) (); % B9 c3 J) o8 A. V; o; `
  函数存放在内存的代码区域内,它们同样有地址,我们如何能获得函数的地址呢?
0 p& u0 O/ U9 H' t1 l  如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址。
, A; `5 U, D- r! R% E: r  定义一个指向函数的指针用如下的形式,以上面的test()为例: 3 G" ^4 \  d" ]6 y6 W
  int (*fp)(int a); //这里就定义了一个指向函数的指针
) y8 {5 S# H! w+ g2 B# ~( k  函数指针绝对不能指向不同类型,或者是带不同形参的函数,在定义函数指针的时候我们很容易犯如下的错误。 . s3 C2 V9 A) f' S3 e
  int *fp(int a); //这里是错误的,因为按照结合性和优先级来看就是先和()结合,然后变成了一个返回整形指针的函数了,而不是函数指针,这一点尤其需要注意!
& m8 E" @8 R& y! O' V' ?: O  例如函数原型为:
7 I/ e# x" ?% X1 |$ \  int fun(int *, int);
' t3 W0 d5 a, ^- t" R. Z7 L% G  则函数指针可以声明为: int (*pf)(int *, int);
+ l6 a* t2 H/ k% _6 L1 d% `% v  当然从上述例子看不出函数指针的优点,目的主要是想引出函数指针数组的概念。我们从上面例子可以得知,既然函数名可以通过函数指针加以保存,那们也一定能定义一个数组保存若干个函数名,这就是函数指针数组。正确使用函数指针数组的前提条件是,这若干个需要通过函数指针数组保存的函数必须有相同的输入、输出值。
3 n7 s. i$ ]9 e+ x  view plain //首先定义256个处理函数(及其实现)。 " Q7 i  y6 M3 I. q
  int function0( int *, int );……
, q  ]+ u; k" B  int function255( int *, int ); " Q9 O/ |0 Y1 d3 O. \" u; S1 e) i
  //其次定义函数指针数组,并给数组赋值。 " j4 f# ~2 k; q* I. _- |+ a, E- H6 q
  void (*fun[256])( int *, int );
! N! W. u8 d/ F- H  v  fun[0] = function0;…… . J  O- O* G* H7 L
  fun[255] = function255; ' ~' b! L5 u4 z' A
  如果赋了不同的值给函数指针,那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。
# ~( |! i4 e2 ^. i3 X  下面我们来看一个具体的例子: $ i/ W" k5 f; x5 W+ i4 F+ i' }
  view plain int test(int a)
, a4 k/ T! d5 r5 T* H4 @# h, l  M  { return a;} * y5 k2 Q5 y: c! c
  int main(void) ) o: T  ]! t0 |2 j. k$ C
  { int (*fp)(int a);fp = test; //将函数test的地址赋给函数指针fp cout《fp(5)《“|”《(*fp)(10)《endl; //输出fp(5),这是标准c++的写法,(*fp)(10)这是兼容c语言的标准写法,两种同意,但注意区分,避免写的程序产生移植性问题!
' X' K# b. ^) W. f  return 0;} typedef定义可以简化函数指针的定义,在定义一个的时候感觉不出来,但定义多了就知道方便了,上面的代码改写成如下的形式:
7 O* t3 n' R1 ?% e1 U1 P) ~* p  view plain int test(int a) * `" l; `" e' H( r# x( }
  { return a;} 2 h7 s4 ]; b# L* X/ U
  int main(void) ; M3 |6 B2 v( K# f0 F9 E( R% W
  { typedef int (*fp)(int a); //注意,这里不是生命函数指针,而是定义一个函数指针的类型,这个类型是自己定义的,类型名为fp fp fpi; //这里利用自己定义的类型名fp定义了一个fpi的函数指针!
& U3 F- c; ?8 m9 R' n3 M5 Q  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-4 11:25 , Processed in 0.366498 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

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