TA的每日心情 | 慵懒 2016-4-21 12:07 |
---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!9 S; U/ Q: |1 n* h, V: l
' _2 d4 ~5 b) H. ^0 C* H! J3 _1 m5 q
在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
. ~2 v4 j* l7 g 快速排序的原型:1 X6 x' C: P3 H, d h
void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *));
# K# l! Z6 `5 x9 \) ?: r/ X V' @ 可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
( j2 v. Z4 U* e3 y8 Z #include <stdio.h> # C/ C! t6 h, a: C0 ]: W
#include <stdlib.h>
2 r E& t% T0 eint sort_function( const
. p' U9 ?9 [: N6 }" Y% n; |void
$ t: {& c8 z. B1 K*a, const
/ P: ~( c% t( ?1 yvoid$ n! h! E! Y% V) A3 f9 n
*b);
, Y' N" V0 X) Jint list[5] = { 54, 21, 11, 67, 22 };
0 o3 ~; n# k7 D2 t5 E* F; h+ [0 X2 ^/ [ B2 w2 {" ^. A7 \$ D
int main(void) 6 p6 @ r* r b/ ?) d
{ % M% m4 h0 ?, w( V; R
int x; ! g$ ~! A" E5 |* G6 R$ |7 i, B
3 h# Z( F3 s$ F. H9 @- M
qsort((void9 h* a/ e0 P% l1 m& }
*)list, 5, sizeof(list[0]), sort_function);
/ E% ^* o% M- b9 k4 Q for (x =
. D: L% s+ J% {% T! j* w) n7 l0; x <4 C/ {$ K& A. m9 J5 d" ^
5; x++) - ]: j1 t+ @( @4 G' r* Z
printf("%i\n", list[x]); 0 T# V" `$ u$ {; [! |
return7 n/ M1 U6 @2 u0 q; f6 k- M
0; * J+ u- J& m! ~3 u+ I6 _/ k! S
}
' @9 r/ W& N# E7 y. {' d9 z
/ r8 ?) A4 `$ `int sort_function( const
( ?& O! Z: Q3 K* ovoid+ t5 _$ R4 J" t6 ~' L
*a, const! B" F/ U! o; q. u$ [
void
, I' [" k; q3 [2 c3 N*b)
4 u4 ?) _# K+ O% c{
m2 N( ^- G* m! N return9 t- k8 c4 S ^) N
*(int*)a-*(int*)b; 0 Y0 N( }$ w4 Y2 F5 \$ x
}4 s7 O% G0 t m, Q/ @+ \3 t
, @1 O3 b- z5 [2 x. U$ q+ M
5 b# m3 p/ @9 T
7 k' s5 P/ L9 r! {1 F* H" A 函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。
2 I5 o) \; C2 V) Z$ _+ w% g! i 下面的代码说明了函数名和函数指针的关系:#include<stdio.h>1 [+ I& C8 ?- J8 G8 a- \* J, c
~/ k# s) }$ n1 |1 w5 O+ N' d
# h% a- R: l7 x
void MyFun(int x);7 q( S3 b4 ?. F9 g
typedef void (*FunP)(int);
0 o" t+ }5 w) V) x; X7 G5 U; G8 I9 X. W8 f
FunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;/ m% U5 z$ t; B; ?) y
5 S* l" v8 m- D- ` U+ B3 n3 F# q
int main(int argc, char* argv[])
6 F. T% {5 `8 c9 J O{) }$ \8 W h9 ?0 r! |: ?
MyFun(10); //这里是调用MyFun(10);函数' @/ D3 z1 \& k2 t% g* Q
+ A2 J0 M' a% \+ o/ C& I+ r, T
fp1=&MyFun; //将MyFun函数的地址赋给FunP变量
! }* | ~" i) m3 r: [! i" j: N/ x (*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。 ) u, e+ o% t0 t& r
3 o0 K5 t* q( `; D% k1 a- `& e2 q fp2=&MyFun; $ T# H4 L0 T! F! @
fp2(30); : \3 g8 B. K+ v
* v8 _ n1 @8 @
fp3=MyFun; , L5 M4 p" u/ j. ^# o& D7 m7 ]. O W
fp3(40);
# U4 Z/ ?0 @- Y- Y, v
9 x6 }0 |3 O) y) w' Y fp4=MyFun;
; v4 j0 d R# T* o: J. P; R (*fp4)(50);
# }& P( B& f: r) u! Q" r) L; _7 H8 h6 |- L. r9 s1 |# `2 n
return
4 i Y j7 \4 B$ H% I/ H0;
( r. @% q, h8 T' A# d( t}. _, X/ k/ P* x$ L7 k$ O# {
& L, S7 N) M% c! nvoid MyFun(int x) //这里定义一个MyFun函数
7 d3 U5 m" T7 `( a4 v8 L$ _, X+ R. Y{
" q( o3 R; x4 O! @: }9 { printf("%d\n",x);$ c; x0 W+ Z7 K
}
5 E3 ?4 i. w+ u/ X$ S5 J' Y' G3 m) l) U+ O! |
: c g2 g* X2 j/ Y6 t6 ]
1 E8 t! ]* M9 J0 t0 L: o0 n5 x
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。& t5 ]3 p1 Q8 \! j! e$ C* y
2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。4 I4 P3 d# P2 }1 s3 v7 S, z# D* W
3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。/ H& h5 n% z/ E7 H! J
4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|