TA的每日心情 | 慵懒 2016-4-21 12:07 |
|---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!
) p4 @9 a2 E4 [* U& c5 V3 t: _# l, |
+ f" C0 B# U9 G/ D* V
在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
/ N# o7 n- T) x* v 快速排序的原型:6 C. I( A# P, e' i4 c+ W# i
void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *));
6 @9 `1 @8 x) X- [* i" Y& n F 可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
2 |1 F+ h' m2 A/ H( H% p #include <stdio.h> . K# L. G' u' ]% Y
#include <stdlib.h>/ t7 x/ w& V% b/ ]( P- X" E. Q, o4 Y
int sort_function( const
' }) k0 @8 x3 s# t, Tvoid$ g" p% V+ r7 a- l+ b, M
*a, const* i" v% M: U) N$ t% z
void
, d8 J8 \9 `5 c6 q) A! p7 d*b); . E% ~" k$ p1 Y* A. R4 b1 N
int list[5] = { 54, 21, 11, 67, 22 };
* z& ]# g7 e, \) b; i! G1 a& U& g1 s. _9 g4 O7 X
int main(void) ! P/ z2 a/ a! u; t3 f% ^$ t. ]
{
3 C/ x* O$ r- i# X. P+ \7 T, P int x;
. P% k' `) v( b5 a$ c4 a
2 J7 ]4 {2 ]! T5 b4 V qsort((void+ S; W9 U' t5 N3 ]
*)list, 5, sizeof(list[0]), sort_function);
' E, J9 u- \# n0 R# F. |1 S for (x =9 t" ~/ { J" ~, {
0; x <
& a- R8 c; K5 |8 d+ T5; x++)
8 T- e/ N9 e$ q9 k) Z printf("%i\n", list[x]);
" F) F' G- w) J. ?8 S- H. F0 H! p return
' F2 U. k* _1 l0;
( B2 b8 J$ K8 y4 ~" g}
5 Y$ ~& g3 t9 @9 z7 U( k$ Y( v* I1 v$ E' @& m
int sort_function( const
; D( z4 Z: c: R0 o7 K) I" Uvoid
: u6 h+ f/ e, v( Q! b7 G/ M*a, const
( J/ ^8 q- K; O ^2 g2 p; Qvoid
# \2 }+ s! P7 ~ z, i*b)
( s1 Z( x# p' W% ^3 u* J$ I0 e{
$ Y6 K+ o3 z! C& F$ B. J& q& n3 X return
7 o$ e; T1 o+ c7 q*(int*)a-*(int*)b; 7 s9 R7 i( |6 I O
}& k8 w) _* i0 x) ?
+ p5 i) M- v# M/ T9 n0 q7 J. r8 ^* A$ G) D
. y5 j2 q7 L4 r' w" D* h 函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。
1 L1 Q: o, |, `& F% q ~* i9 |6 V 下面的代码说明了函数名和函数指针的关系:#include<stdio.h>
' h2 T6 d- U, R! p6 o) t% v9 S/ a1 U4 ?+ d! J8 S3 S% ^- {3 [
0 m" G( _, b6 `# N: r/ D$ V
void MyFun(int x);
% C" r" Z t! K3 l+ r; C" jtypedef void (*FunP)(int);
; \ a( b, r3 G# W/ Z& _. F) V* F/ f& U( s7 r4 H' H3 J
FunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;
: z" @. z; |( y1 O: p+ M
/ n& D9 S k. c0 D, m6 Sint main(int argc, char* argv[])) J1 h% ^% D- C0 h$ u( S8 U
{
5 Y# @6 ^' X8 s) \3 _( |2 D MyFun(10); //这里是调用MyFun(10);函数0 Z% `: z- b1 W: w+ |4 l
7 |; l% S# f; @- k0 |8 F
fp1=&MyFun; //将MyFun函数的地址赋给FunP变量
- s: ?3 M- k* D/ h! Z2 L (*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。
9 g; a2 a- }* a9 J) \
3 l( \; z2 r4 F% ~! a, u fp2=&MyFun; ; G& ]4 i+ Z" C% m! C# Y1 ~( L
fp2(30);
1 v b- O7 m$ C0 E5 n! l. N6 O0 |7 q1 I. _$ s N! S4 O
fp3=MyFun; 0 s" v% N {; B; v j5 H* @* q
fp3(40); * v# J3 ? @ M
% t& ~- W+ v& o2 U/ g
fp4=MyFun;
0 Z# Y# u( \ b3 V7 A# w (*fp4)(50); : }3 {) ? \& U N) n
& X4 P! D1 a, @2 ~4 j. i3 [+ ]
return
* j; E; {; Y% W1 l2 D. v0;
; l$ c8 F; Q6 ^}
; \- V# Y; F N. Z* |
! i4 j u. p: r- H: Rvoid MyFun(int x) //这里定义一个MyFun函数
! g! k. f( C. M' W{1 Z6 G U3 V7 S
printf("%d\n",x);
' @$ I* k% v1 l8 _; [5 W0 y9 z1 `& W# W" t}5 I* M* L7 q2 c3 K
1 `6 T" ^7 M q0 S+ ^/ S" @3 \8 r
, j7 z+ ], @8 `& o7 R: i& u
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。/ z" @2 J' k7 c3 q! u3 M3 D, H/ |
2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。% ^2 ~* y: d& l* Y2 P: P+ g
3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。
U1 c; f5 H L; |! p4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|