TA的每日心情 | 慵懒 2016-4-21 12:07 |
---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!2 i& W6 ]2 f' ~1 h
: S. P, m# D& i( y+ o& v% a* b5 L
x! u% f# { \" L在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
3 C9 I: ^' v' ~- C 快速排序的原型:) y8 W9 y5 P7 `5 ?. c$ {9 F2 Z& n
void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *)); 2 S- _6 f- C1 b* f
可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
4 Z3 i4 ?# o2 z. w4 T #include <stdio.h> 0 s9 P( Y+ @' D/ T- {& [
#include <stdlib.h>
3 Z( B+ B2 |( K5 \int sort_function( const" a- T6 j8 x5 J- n
void
6 ~6 K& E7 V! I0 A% U) ^*a, const
2 U. C% Z) v9 T0 O2 Tvoid. E: X% S& W9 }* ~' n: M% S
*b);
% W: g1 K+ A+ V* a, v: b, Fint list[5] = { 54, 21, 11, 67, 22 };
( q( |( X. R5 x* |. D: Z- D& \0 N$ g: k0 j& q- u
int main(void)
7 P7 f3 [0 l9 X) A; W{
8 L( c8 k$ q. E$ T! s7 r8 y3 a! i int x;
6 X% y$ S; @8 @6 G( r0 S
3 ]' `# B/ g7 q3 |5 l# b, ] qsort((void
2 a8 p/ q4 E& E( [3 `*)list, 5, sizeof(list[0]), sort_function);
, Z' N( q- L: a7 h; t for (x =
6 O# m3 q# C# l$ d6 E, p0; x <
% f8 c$ N6 f7 T' L5; x++) 2 f i* L' J: b- B
printf("%i\n", list[x]); 1 v$ b) O9 T6 @9 c
return
& x' M# T2 Q: P8 K, l4 }( Z; K0; & y5 d/ i; k2 I9 ]2 U
}
; P4 g6 z! I7 s m9 o3 g8 m
* Q4 B) }& K) G' |, tint sort_function( const0 v- i% f: A2 m; t8 g6 n6 N
void/ J7 V$ P0 O$ c5 k
*a, const& W9 `# X. E5 M. R. {" w& ~" h
void
' n5 G3 H$ K4 j3 K*b)
: }: V! V6 K) w/ \$ o, F{ \% r1 w! e2 o
return! N N5 g3 p8 n5 [1 o$ l
*(int*)a-*(int*)b; $ c6 \+ ^7 N: L s
}
1 @' n# y( e+ c" q) ?7 J: k. W" h+ W; j+ w2 r" Y. V% Y& H' @1 n
4 e. V6 H/ Q" P) B7 `/ g( S( m' f+ f3 V! M8 N8 a S
函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。" G6 ~/ _' q2 d- m* \- j) Q
下面的代码说明了函数名和函数指针的关系:#include<stdio.h>3 [9 j& m# G+ U ]# M
! l- c6 H }8 K; k, l: D
' R- a) u1 F/ q. s4 |, _9 C8 ^
void MyFun(int x);
/ K! l5 Z& A( W+ Vtypedef void (*FunP)(int);
^$ H& D' ^+ L( [3 a0 k$ N% e5 Q3 ?2 k7 g$ i% @* Y0 J
FunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;
7 _0 I+ G' L7 _( M3 `+ Z4 z7 B4 I6 e, h4 x" c. |: a/ L- b' z
int main(int argc, char* argv[])' i9 d/ g1 V# B* V
{
% V% P7 n8 P( k+ ~ MyFun(10); //这里是调用MyFun(10);函数2 [) J) }( r1 Z/ @& N
' l( | q% E |; }: ^" N fp1=&MyFun; //将MyFun函数的地址赋给FunP变量
, N# i; r/ X9 z+ q4 L* P4 \3 | (*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。
9 A, ~. D. n0 k* }- W2 n. H* A1 L
" _3 t8 M* A1 t! r: K7 j+ H fp2=&MyFun;
8 N, l. f3 d8 F3 f/ L- l fp2(30);
; K! j, T/ S" d }% ?3 V, W# e7 P' ?
fp3=MyFun; 6 b5 H5 ~0 V# r M' O: G
fp3(40);
6 Y' V' i0 _, V/ P$ w6 V
d2 k3 A( F+ F; U fp4=MyFun; ~9 }+ l E+ m8 J/ e! J
(*fp4)(50); 4 ~+ ^: b- l1 W. a
S2 a$ ~+ j; Q" y5 [% k0 \0 X return
6 t$ e: b8 M# ^' B0;
0 Q. y6 V; E8 I3 K3 P8 u+ o" `}
4 {) B/ `8 M" L5 s. l) m1 X6 c$ c' W5 k- O8 d! V* ]
void MyFun(int x) //这里定义一个MyFun函数
, L# R+ L' d# E$ O{# E8 E0 d$ S! R; s
printf("%d\n",x);
- m' n/ B9 Z5 }! A}
5 E7 L2 a6 S% i2 j7 c$ D/ `: P0 I1 T2 f3 \5 Y
# ~1 O9 D% T' y5 D- @& K9 W8 A4 J8 h \
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。
! }( _9 U; A; j% ~7 |! k$ ]% A2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。7 ^9 n/ t& W- \
3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。
6 E1 u4 r, T+ G6 r, y4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|