TA的每日心情 | 慵懒 2016-4-21 12:07 |
|---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!
3 s: \4 x1 o% C2 b6 c9 g2 j/ S! T- Z4 G3 U4 ?/ b2 c: I+ v
0 c, G* B; C b" R在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
+ C: ^& l+ S5 ?% [7 J u 快速排序的原型:, z6 s1 ?5 X, c+ ?0 w ?
void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *));
' R n$ [, W! c' { b3 ^1 D5 x 可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
5 j2 i" t. F9 M2 z3 g/ ? #include <stdio.h> 6 U9 k: }( ?& ~0 C X. d& I i
#include <stdlib.h>: m0 R* ~- ~, a- A j
int sort_function( const6 J6 ^. }) y6 U# w- G
void
8 q( [ P' S. o, n*a, const
: Y) R1 \/ [9 I f8 j9 Kvoid, e0 X0 D( F9 m! _0 t% k
*b); E! v2 f; l. f6 ?
int list[5] = { 54, 21, 11, 67, 22 };
8 x% x# t g. F* |& T8 a, R0 A( i* b2 Y
int main(void) 5 p8 G+ ~6 \: e9 c+ a
{ _" {- s# B1 k H
int x;
; n% b& }8 E' E* Y+ y' g7 D% g
: B( {/ i, P }2 c% \ qsort((void/ X8 {. y+ O( l' l4 n K8 A
*)list, 5, sizeof(list[0]), sort_function);
, m* N/ k: a: g2 i3 [ for (x =
8 k% y) F' a# A- i' d( f3 U0; x <+ E5 _- U9 Z0 L. _
5; x++) . R; a' F( s# J9 _: J
printf("%i\n", list[x]); 9 j3 o/ b2 k' u1 R5 v# x9 D
return
) z1 j8 i [/ U* a0;
7 K+ K/ G7 x! h: |} 1 a. d, R6 z* \+ ]4 M/ v! }
4 _4 n- i/ m) w M+ Y/ H. J! e1 R nint sort_function( const" T; p+ F3 v/ O' V8 C: k; p5 e
void
4 j% y2 G, q; W+ U+ S" l*a, const9 f. ?6 w$ X, V' l& j' Z9 {
void
5 n. p5 n# E! Z. K*b) % s8 X/ K" M8 Z1 t/ ~% n4 ]: l
{
N6 L" P6 \' Z( u | return: N; T$ n$ D s& s& g4 h
*(int*)a-*(int*)b; / h1 K; ?. |" m! Y; j+ ^! w; x
}
7 a; X6 H& q& {! `9 L* i2 Q# r
9 m; v/ N; G: H2 {* t4 f! F7 \; q; B* W: z4 ?6 _
( H$ t2 H9 ` S$ l
函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。
# G$ q: q$ Z4 E* Y- W0 O8 F0 @- ^ 下面的代码说明了函数名和函数指针的关系:#include<stdio.h>
# g# u4 w3 U H# L/ d) ~/ S0 C+ Q6 j
+ u; Z% N. u& s8 K/ l) Y, ]void MyFun(int x);
& m4 t' C+ I/ \, E { `5 Wtypedef void (*FunP)(int);
' C1 F6 p/ n! C& B0 X* x! _5 I+ K- w
FunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;
4 s u. e# V" O6 y: k. p `3 f' Y* ~& s, n% f5 ?( J5 Y& p* t
int main(int argc, char* argv[])
) J' l$ ]0 [: V{" n5 _0 K! r2 `" y/ h/ t
MyFun(10); //这里是调用MyFun(10);函数
! n2 X' c; o8 R: Z- r
: |# |& a7 [2 Y; w. D- K fp1=&MyFun; //将MyFun函数的地址赋给FunP变量
. s: q) D$ e; E1 E+ L' ]- W/ Z (*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。 ! v! ^5 P& i" @5 h6 l# Y; [8 m! ]
. Y. Y( q# `6 c8 L fp2=&MyFun; , z! s1 z" b) P! u
fp2(30); ; s" L& Z6 p. V4 e L* o. l
, g) z; F9 J8 E; K* C8 B
fp3=MyFun; * f2 I+ E( \6 ^
fp3(40);
2 N4 w3 B. p) B4 x, B6 R+ [5 K; X Z6 W j
fp4=MyFun; K5 h! N+ Q. ?: y9 ]6 G/ {2 ~4 r
(*fp4)(50); 0 ` U- F( k# z
' [9 \3 q0 G& s
return
# L; y) e% o( P3 U" N; K0;
/ `$ |3 ?- S& M: n! h}) T! |' z! w3 N( ]3 F
" E: ]3 e% v) P& I$ Tvoid MyFun(int x) //这里定义一个MyFun函数/ N& N# u. R$ y& _2 W4 m
{
" K7 `! M3 P% O printf("%d\n",x);
n1 H) z7 I: H} J/ M0 v) O B! b
$ F; q# P* {) O; Z- |! d
: D' O% r( @* ]% O
* U( p8 C* g/ |8 U$ U0 h0 w
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。
5 f" h3 L q" _' `* `/ F2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。/ S h2 H5 o" v4 W/ A
3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。
) C: X/ J1 g6 D# Z& G2 B4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|