TA的每日心情 | 慵懒 2016-4-21 12:07 |
|---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!
, x% u& l: \+ s( Z
* X- y7 I2 F% }% v! n0 [
, K! w" R9 J; `在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
/ H/ w9 T( q9 t5 D5 j 快速排序的原型:
, v% N* [% s, b5 L void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *)); ) u, E6 T8 L! S4 b6 _ N' W
可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
6 Y# Y0 |$ ~+ _- D! Y, b" V #include <stdio.h>
: l$ N3 c- V: o#include <stdlib.h>! @5 C# I& m5 q2 H8 z% G# q( @! @- Y
int sort_function( const4 x" ]0 R! j, G* W. e& R
void
* `* c9 Y* N' x& O! n7 F5 I( E# Z*a, const- M- K: I* z. l7 u* ^8 @, W' x' h
void4 O, @2 O- X) J/ V6 M- v3 K/ m8 `
*b); Z1 Q! G" K- G5 J) z
int list[5] = { 54, 21, 11, 67, 22 }; " x A) |3 x; C$ F' X
% V) Q! B8 M8 E8 [6 Hint main(void) ! j$ [) }* Q4 x9 V: p& ?+ c9 M' a
{ ) M/ t, I7 [0 m' S( p9 p8 v9 w2 |( t
int x;
$ R+ I/ a/ a; [4 P8 s
# s& ?3 D% i7 B% f8 X qsort((void& r- v" ]# }: L- Q4 h' J& S& ~% Y4 \
*)list, 5, sizeof(list[0]), sort_function);
" U! G3 A. m; ]: a! e for (x =
& m. V; V6 r( N) V3 y4 E! Z0; x <
+ \# L3 z) D1 O6 p0 C% ~8 `# C$ Q7 u5; x++)
$ @; d/ z, u6 W( Z4 s6 w printf("%i\n", list[x]);
1 c& Z9 C$ R: d8 S return- H# H) t7 a1 l9 C; K
0; 8 o7 [+ f A4 Z$ q% p6 s
}
- m8 h: o8 p& {0 S3 ^. g6 B: u( e4 x; A4 _
int sort_function( const% @7 \' L1 ?' ^- z
void
* @2 h u- }: _; z) V. i*a, const
* ]; H& e- }' q3 h4 ~! k. nvoid: _( `( i5 l/ w* N0 g- u) d
*b)
! [: `4 R- i7 L9 o{
$ Q3 G; m( N3 n( Q return
: E; r0 n' w$ B( n7 q1 _. c$ y*(int*)a-*(int*)b; 7 ]) q; w. h! k; T$ p# ~( J
}
( g2 G* v5 ^6 v. F; E4 x6 u
. n$ J$ T6 h- [
. k9 f* [! L/ E
. P. _/ K8 K& F5 n0 B7 V3 [8 b 函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。
F; L* a7 G4 S$ X6 }, N 下面的代码说明了函数名和函数指针的关系:#include<stdio.h>% y! |( k, Q2 k9 [
- a. K I# e# s8 k
0 b7 r6 E0 ]. A. `$ Ovoid MyFun(int x);+ {: d5 ~7 ]9 L/ m8 w
typedef void (*FunP)(int); & A8 {& W/ `1 X, P: N5 N# W
" [1 f5 f6 u5 i: GFunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;3 H; d" E) _6 b, o4 k+ R o, L4 H$ j
8 C; b3 ?8 D3 ]& b
int main(int argc, char* argv[])
7 S) W! V- f# e7 U7 v) p{
9 {3 `4 I% u* a \# E# { MyFun(10); //这里是调用MyFun(10);函数% \' |0 c+ X5 \# _6 [9 E. v$ o6 E0 Y
7 B7 T7 m4 B( |1 K% |. z. n1 s fp1=&MyFun; //将MyFun函数的地址赋给FunP变量
/ ]& J5 H. T& D, L. `' |& L2 ~, ` (*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。
% `" g: a8 b% U' Q% V4 @+ Y2 z& x% F. y5 ~) h$ W
fp2=&MyFun; 4 S. o V' X ], ^
fp2(30); 8 G3 c1 m( i& c0 Z% O8 E
, q+ D! }( d) \: V9 C fp3=MyFun;
4 U3 [, A6 O! d; k fp3(40); 7 X3 n: k) i" x
- f) C; q/ k: u6 j0 {; c a Y fp4=MyFun; ( Q$ }8 a d! |& i) L9 P5 m. g
(*fp4)(50); ; E/ f+ _, }; G6 I, d1 ]2 W
# i/ L. _3 i `8 c5 ? return, ^ Q$ s( X, w( | r
0;
; c6 ?/ V3 V! t, x$ `( ~7 n}
8 I {6 O. U& g2 e, q8 H
W1 e7 r: C8 |" Wvoid MyFun(int x) //这里定义一个MyFun函数- i. x$ C& C& G# |5 g
{4 k( S8 a9 {! [3 ]' d2 @
printf("%d\n",x);
+ v; ^1 A( \7 x7 n}
/ j2 \( v- a6 e+ N' ` s; v" i( f V# S# z
+ d0 l, _$ a7 b3 K4 Z, P
% s3 K3 c3 y( x# w
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。
% w% N! v# S6 i( m0 ~7 L0 w9 Q. T. A2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。
# T/ ?6 X/ |! E# T. G3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。; c0 M/ _; ^+ B9 H
4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|