TA的每日心情 | 慵懒 2016-4-21 12:07 |
|---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!1 J2 }+ ?5 q+ K; J
* Y+ e4 g# a. e+ U* `, \
4 T: }* v: m! g8 f7 Q
在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。# D) @& H8 ]0 g" n/ X8 f
快速排序的原型:7 m4 ?5 [" w/ ~8 G# H
void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *)); 4 G( t) ]" K7 E. U. \+ M6 ]0 B- A
可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
, `& z* @; y# P# p8 l' ` #include <stdio.h>
- U' q: E) f1 c b6 h: Z# A& t- j#include <stdlib.h>
6 z9 R: K0 J' H5 u+ qint sort_function( const9 P) X0 f. P( ^; t3 |
void
0 N$ c% j5 N0 Q* W5 b*a, const
& q' @& S6 n: z3 d( Vvoid
2 m0 u4 \- ~- L4 W* C*b);
( ?! ^. Y9 Z2 u/ g/ N! I2 M, eint list[5] = { 54, 21, 11, 67, 22 }; : J0 b; O/ q) k9 v
, B/ d! ^6 ?* P( l7 K/ N/ ~1 Fint main(void)
4 a/ _, j _6 `) J{
( _$ z& K$ s! z4 T int x;
( G: F* [, C! S3 p6 {
9 G; {* Q% _& T% s$ |- w7 g8 y$ { qsort((void+ L$ H# @- K; |7 y8 ]+ Y- i; w3 e
*)list, 5, sizeof(list[0]), sort_function);
6 L5 p }1 I) N2 s for (x =
3 R/ I- w- E1 Z5 Y1 V1 P0; x <
! L& s2 w1 n7 R3 R: i8 R: c9 B) Q+ o7 Q5; x++)
8 B& r* u3 j8 D, h% @ printf("%i\n", list[x]);
3 G2 }1 G+ _4 v D- F return' S* [2 e: P, R: m& k7 L. q2 X% I5 {
0;
0 k P/ E) K# p* a! k: z}
8 v" h: G) j% b, v( l+ G4 ?- E6 _$ r$ B- v
int sort_function( const
% n: {4 F8 \' J3 v. gvoid) S- P1 Y5 K! J* m1 Y* ?% p1 Q q
*a, const
1 M, E$ D5 @ Z! ^$ P0 C8 evoid
& @( v, w2 e5 ^3 Q*b) ' S7 N' t9 v% i+ A& t
{ 0 O. t9 F4 g$ a0 H( v& U
return) N. X }$ |# E9 A& l0 ~
*(int*)a-*(int*)b;
" E5 W) }5 I; K- j6 M2 B( p}
, T5 C" B5 [5 p3 C( N
! g! D- j# y* @4 s
2 P4 F2 p& q1 ^$ p" @
& z) z+ q3 T( R1 Z p0 f+ i 函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。7 x Q# u; U8 V L) E/ D% o
下面的代码说明了函数名和函数指针的关系:#include<stdio.h>* ?& M: K" E2 B8 U7 P9 J+ P; k
. Z1 F$ W7 U" W* @+ M( _3 l
) c0 K' y2 f" [ Q2 M0 Lvoid MyFun(int x);
# w5 P* c" f0 v- Q9 B! Atypedef void (*FunP)(int); 4 ?2 G6 r, l) k; i$ {
. y, N( v( B, n4 g" f) }
FunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;9 i5 v/ m1 s( Y! z( s! h. ?
( T( G2 Q/ @; c) h( _% W# k5 ]+ H& xint main(int argc, char* argv[])
. q) Y3 m+ _( y. z% z{0 R3 e: G9 ?: ]+ |
MyFun(10); //这里是调用MyFun(10);函数+ ?2 p/ j _7 T$ J
, a5 o! F1 O: x6 q I* M6 B6 }4 j fp1=&MyFun; //将MyFun函数的地址赋给FunP变量9 K# r8 f6 w7 ~4 {# @1 V
(*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。 ( e: Q# f$ N) }; L; A! \( Y" f
, K# Q6 k/ E0 B* S8 Z! X fp2=&MyFun; ) l. v* d( v' t0 i2 B
fp2(30);
% V9 e! |# O4 L/ _/ M* t
2 Y) } z5 d; F T7 m' O fp3=MyFun; ! w3 t; Y# G+ Y0 G% W
fp3(40); ' U7 e ]" k( y4 g. E4 a
/ j/ x! ?3 P8 P( y" ^9 `
fp4=MyFun;
1 [7 K H4 w' Q J- @1 s (*fp4)(50); . W* M# Q0 \) L1 ?. @4 H8 T& A
. \7 d, g: u% |% E, I$ H6 o
return
; L ]+ v" b1 z: p0;3 H5 c4 Y, t8 F) L
}
$ r! |9 M$ Z3 [( t8 j' g) N. ^: H9 g
void MyFun(int x) //这里定义一个MyFun函数1 L! `5 T: ?( s& y! n* B
{- y9 Z N' j; Q
printf("%d\n",x);
( n# t$ [9 c: F+ V8 }. @}: ]' D5 P( ` s4 W; s8 i( n
4 u) z/ e6 x' D6 g' H
1 i- E3 C" Z! r1 S& ]4 C1 b# G
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。
8 n6 u" a3 Q" D# t2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。7 r* Y) j& F) u7 l5 R
3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。# R$ o4 z; U3 |& i# A5 V0 P% {, D
4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|