TA的每日心情 | 慵懒 2016-4-21 12:07 |
|---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!
: a0 q4 {8 a4 Y% m0 {' k' m7 r+ L- o7 V( w
. z4 O l+ w; U2 U在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
2 {6 P4 V! s0 t g 快速排序的原型:$ O0 s$ r* d: A$ `+ }- g
void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *)); 6 u; d+ o! i6 B) a) X- ?
可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?$ p) O9 y( v, F# N
#include <stdio.h>
( p. f, u% j7 C4 C0 f#include <stdlib.h>7 s3 m. s0 k4 A5 Y# s' \5 s
int sort_function( const. v0 _+ \4 G B' b6 ?3 O9 [ v
void
! T, i/ H% {" K. m- a*a, const" R# C7 L2 i4 q8 O. l0 f$ M
void
. \5 G& |+ K/ }5 B- w" r8 F*b); 3 I5 J+ V% E" s. z0 I3 @* p! F
int list[5] = { 54, 21, 11, 67, 22 };
$ l5 ^- u+ B3 _, J; K4 i" H* r; x6 `2 o+ v0 M- V/ i5 y& f; s
int main(void)
; G' t2 n Y# @9 F+ |) p{ 2 y1 d( g/ h6 s% A: g+ b
int x; 4 u$ N% }* E: D
, i8 D2 d# {) H5 |8 @+ X( I- t
qsort((void0 e8 {$ P3 t$ [& T& c" D7 e
*)list, 5, sizeof(list[0]), sort_function); 6 j9 ]5 P7 O9 Z: K
for (x =8 n& @& E5 K6 s- t0 Q! K0 o
0; x <
* C+ {" [( G8 w/ c" [6 b5; x++) ; l: S2 k7 z& {
printf("%i\n", list[x]); 1 g! q( n- t6 r" ~$ o) E
return8 O$ |# g, G( ~9 x0 B; C
0; + O O4 }' x3 ?
} 5 g1 N6 l9 {4 Y: u
3 a' s P1 A U# P& q" u$ e7 v# |int sort_function( const/ J% U/ C; K5 u, _
void: F/ ~8 v; f# D8 R$ b( T! \
*a, const/ Z- e2 X9 l" [ F7 q
void+ n4 ]& e8 D. a" b: `* @
*b) 1 q( i2 L$ `1 u- f5 q+ j
{
5 {8 i; K2 |5 N i8 I return& K+ ?6 |1 w/ v0 r% |: J
*(int*)a-*(int*)b;
|" l! m _2 v% ~8 P+ F. |6 y}
3 u4 {4 P0 W( H! a& m( U9 R( S
( N' O- A2 Z7 |5 n& \$ m b( [. d( ~/ U
- P, N, G- W5 L/ }: P4 }
函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。
/ D- M# U: n* z5 K: [5 U5 N 下面的代码说明了函数名和函数指针的关系:#include<stdio.h>
" I/ w$ L& U- B4 B: X+ a( v$ Z
5 _. j! Q, B, _9 v @) G% |6 c" Q7 w7 Z5 {% ?: B7 V: w0 j
void MyFun(int x);9 c: V) e7 Z! d- b7 ?0 s" \
typedef void (*FunP)(int);
+ m9 v$ a+ u, S$ I6 C9 c
( Z: w8 v7 f1 p2 S v9 SFunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;+ ?# H' @' z% J; g5 ?
( O, J$ h) z) [. t3 Kint main(int argc, char* argv[])- b- H# A0 [0 f0 ^
{
' j/ t2 F0 ]/ L MyFun(10); //这里是调用MyFun(10);函数. `- V$ t2 `9 Z" }& A% g$ q! o
; ^6 U3 x; w8 ]4 p9 ^8 k fp1=&MyFun; //将MyFun函数的地址赋给FunP变量
/ r- a7 W! Y4 c1 `" n (*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。 ) x2 C3 d0 c4 ^' m+ c5 B" B
' d: R& {# S% {. n
fp2=&MyFun;
8 H2 X; n% c( o* ~) \5 ` fp2(30); 6 @) e1 ^" x3 T! M
; n. X4 Q, K4 d: s% R: }; \, _6 c fp3=MyFun;
' t' a* Z% I1 a. [, n8 H8 ] fp3(40);
4 g0 Q# K& b$ V& X ]) T) A: `: q; I8 M1 u
fp4=MyFun; " g9 ^9 ?6 j P$ h' w
(*fp4)(50);
& T6 o) o+ q8 Z$ t
3 @0 e/ l! ~2 T% W return
. |1 m) a3 [% d; e% J! h' l3 L- m* A* a% w0;' d: S5 }+ l& ?. {3 q+ u/ i# W ^7 M
}5 V( o* p" b d1 L; t* h
# ]: w# P/ H4 h/ t; A. t3 ^void MyFun(int x) //这里定义一个MyFun函数$ e$ f% P) {# [; E9 `5 {3 ]
{; N8 ]7 _* l6 Q9 j8 o
printf("%d\n",x);
/ Y) Y' E4 T9 x) g% s}8 q' M" i+ y' F/ w$ _
0 ]6 X: X( I9 H- }% p* D
* y( l" v2 o& Z& P& d# M1 k3 K# T! j @2 ]" a
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。
4 t+ Q; u4 }3 L- ~% R2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。3 a. D4 N* x8 }# r1 ]1 S
3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。
5 ?% @1 _, k' J# N) P4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|