TA的每日心情 | 慵懒 2016-4-21 12:07 |
|---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!
: \% ?, e4 M6 C a& Z3 e
& `4 q1 F" q3 K+ i# p* ^5 `) D. g* J \( Q( A2 W% }5 b1 X
在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。0 P* i: g3 W; C4 a! q# ]( C8 c
快速排序的原型:+ u; G' J, V6 O5 }1 O; R
void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *));
* g6 k2 _* T5 n/ y% U. Q( q+ u 可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
' d1 N; P# V2 C4 w! H- B #include <stdio.h> ! L E2 P% r# K9 @# y( }2 F' M2 X
#include <stdlib.h>
+ |9 c+ L. g! s% P' T% I4 C( rint sort_function( const5 \; w! T" l# W9 r$ Q
void
. \6 @$ T9 T- }*a, const
7 Y: O: U# t# Z# Evoid9 `9 |$ Z2 n0 i* J$ `
*b); ) l7 e. E7 g+ t! C% w+ M
int list[5] = { 54, 21, 11, 67, 22 };
8 z3 A% D! Y! j9 k
4 _- N1 t% x$ P" z& Pint main(void) : R' N7 x6 x, D+ C# j
{ 5 O2 m$ A: m; ~0 G
int x; & o: L. c% ?9 |( n) Z( V
; [ B* Y/ o' `' [9 E qsort((void
6 Y" q8 P) a* a7 @% B0 b) u) R8 ~*)list, 5, sizeof(list[0]), sort_function);
3 @8 x C8 e1 t2 i! J+ a/ A for (x =+ ^ Q4 q" z4 u& f
0; x <
# d/ ~: z- p+ m9 @2 H8 d" Q5 r3 b5; x++)
}" i1 M! y7 \; r printf("%i\n", list[x]);
! P! o6 @5 e& n6 `$ z6 R6 T return$ s8 q: w3 L5 g8 t- M
0;
$ W$ H' l2 d* Y7 b8 e} * r8 h" Z) r0 F2 M9 X
5 U1 F3 Y* u. U6 u5 Y4 Uint sort_function( const* S3 \: Z+ w$ l' |/ V, k
void t* u8 q+ T9 R [( M3 G; _2 z2 Y
*a, const3 W* W' t( R# f* l
void" H* L9 ^; Q) o- g3 _$ I) n
*b) 9 S" d9 F4 `. p; R
{ / \. h& \! _5 e! T% n( E
return
; g- E. G2 w7 G; s( `4 N! ^*(int*)a-*(int*)b; 7 j5 @% d1 Q; d" P! D/ P
}
5 s" q2 V8 F$ X/ z" ?/ _
) p; T9 A, v' C) H$ [ g
: q' C9 N% U; X: `, ]% a1 v4 N' \; T* Q. z8 H4 V
函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。* J5 a' a% m! p( C) X, T
下面的代码说明了函数名和函数指针的关系:#include<stdio.h>
* I$ u* i! v P6 k( d1 z
- K% e! `* M/ _! Q) q3 Q! ~; ]7 V; _+ V u
void MyFun(int x);' u. n n( W4 ^: H7 j* |
typedef void (*FunP)(int); 6 k: E* N; `7 m |2 d) j
2 I' C* d7 d% S \* L% G8 L L6 UFunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;
0 G- {, b: N5 D2 m7 R1 D0 c
- @8 Y& f V: D8 |int main(int argc, char* argv[])$ Y4 ~' H2 A! R- a. O% Z* {
{
9 k. T+ _1 s& ]: y5 k% A' P MyFun(10); //这里是调用MyFun(10);函数
8 P: I' S/ ?" e' D9 o! \3 _8 w; ^7 Y5 n) p. Z
fp1=&MyFun; //将MyFun函数的地址赋给FunP变量0 p. l; h1 M( [6 g7 B( f
(*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。
' ^& Y6 p/ F% d ?1 t4 E; c4 \" f! R/ L
fp2=&MyFun;
! C4 K+ t9 m8 ?: t fp2(30);
0 _: n/ J) j# p O6 d L% J4 S- N- y5 z( m. I4 P! V
fp3=MyFun; / }( h* H0 t- z7 x1 y( r
fp3(40);
+ B& R/ E7 U7 Q: m2 x! C' j$ T2 u/ D
L& c3 ?1 J" J, N" P( w fp4=MyFun;
, a( A$ f" y' n! W; e# p (*fp4)(50); ( b' ` {9 I N$ t
: y1 ?5 ~) y6 j& x! C
return
* j9 _' w2 M; x" P3 h0;0 Q" a2 m; \. R- E, f
}/ x/ O8 U1 [) F3 d7 Z# y
, L/ c2 N% X8 Q7 y1 S8 Fvoid MyFun(int x) //这里定义一个MyFun函数
+ X, {6 d! n q{( ]. v9 B: T2 y1 o
printf("%d\n",x);# C& K5 L/ Z5 U7 k5 h
}; d: J" H+ [/ w/ b+ T1 `) H
2 [2 p0 {, c; R3 `
9 w( ]0 k0 z1 y: r% a- N8 z! d7 v% U0 n; T/ Y+ @# ^& U
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。
9 H" {( I2 q! Y/ y' u3 v% x# }2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。
9 I6 W4 W% |$ \3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。# O b0 X) W* m
4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|