TA的每日心情 | 慵懒 2016-4-21 12:07 |
|---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!
7 \. a3 j' K5 _& q- r/ ]) H3 v4 k5 W$ o/ }5 u
: A3 p# j1 ~$ G# |& ?8 T6 b& L
在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
. c: N' p2 @, q" m! p; s 快速排序的原型:
1 q9 X) E5 |/ } void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *)); * x5 ?( z. U9 n/ `- R/ o5 K
可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?, I- G' N3 L1 o: o
#include <stdio.h>
) \! P7 o9 _; e* g2 h( r#include <stdlib.h>& Q% M. ] Z# f7 y$ D' p& ~, `
int sort_function( const
6 y C" I. O# Z1 \. V& evoid, |2 d, t6 [4 u; a
*a, const
. F9 y. e$ `. }0 ]3 evoid& w8 _# \1 q3 {% C( p
*b); # ?3 ?; C, Y. u$ d0 _
int list[5] = { 54, 21, 11, 67, 22 }; ! t' X0 ~8 R- ]
( l% n5 o% r9 K0 s
int main(void) 6 @) [0 V3 h' _, A
{ 1 _6 d. E9 f$ L% }% p+ Y0 s
int x; 6 o/ W2 u9 ]' k
. D0 `9 l/ b: c! i# Y7 B qsort((void0 f( f% b Q0 T0 k1 z
*)list, 5, sizeof(list[0]), sort_function); 9 E7 Z, ^' F4 h
for (x =7 \! M: u/ W3 i! {# `8 g
0; x <' [1 }" _- M/ P1 M$ V
5; x++)
8 H: a. V+ m" E6 ~; N" x: C6 ^9 R printf("%i\n", list[x]); k9 O' ~6 A J& ]
return
1 C5 J1 J8 f- q9 I4 ]0; * |3 u' o- r: ^2 h* p2 n
}
7 a6 A6 r' ~ ^9 ]
" D9 o- z' @: v! R$ Xint sort_function( const
) {) k6 O# ?7 Z& [- [' D8 y# Ivoid
" H) ~ J& d2 y& A*a, const
; K0 }+ W! j; l0 E0 o& fvoid
; W* U6 X( W7 z7 b" G% |2 A8 p*b)
4 B) G) f& Y# W7 ?5 m: G{
; e7 k O! @* ? return
& @: A( r& D& `' M3 t2 \' W, T0 B*(int*)a-*(int*)b;
2 ]6 \1 X8 L% H8 G( @}
7 Q$ D) }5 p8 S0 ^: d
+ q- I+ {' p! _1 X8 K4 n. C+ h$ i, @
. S' a! r: }6 o. f4 Q5 ` 函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。
" l5 Z" q- k& H2 u9 o 下面的代码说明了函数名和函数指针的关系:#include<stdio.h>
; B9 \8 t# [# a' f! K* @
k) z8 ~: b& ]/ \
; L7 }; d/ ` Q% h! R" [/ Mvoid MyFun(int x);" {3 v. f8 q# g; J# R
typedef void (*FunP)(int);
+ g' M7 ? c- P0 d4 L3 F3 R( R8 g
FunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;( t& H3 B6 T& i) [ X, A+ g
+ k4 {, S) V5 C& y' K; b
int main(int argc, char* argv[])
% [/ e* g7 W: ]3 ^& V" N: J2 M5 |# |{
. V2 z# q9 R% p/ J5 E: c, R MyFun(10); //这里是调用MyFun(10);函数
, `* R2 [2 E- l, ?1 h5 U
% s k' h; P) I. D/ s" v( } fp1=&MyFun; //将MyFun函数的地址赋给FunP变量5 J' Y6 N3 a) M: D
(*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。
$ M, n9 B* _( ^+ k' T7 \1 x$ a
. E0 _" n0 c2 L6 A! Y fp2=&MyFun; 5 c+ c0 g0 ]" i& d
fp2(30);
+ Y0 J7 a* a- {: x, Y' |
$ c+ @+ z! r+ b7 W- O# K fp3=MyFun; - m" T) y9 m" u
fp3(40); # p+ e/ J# W8 L; I1 k/ a
: A0 s) s" P; r. ?$ ^+ r* a fp4=MyFun; / V/ f j0 ~0 ~5 C8 i% a. H
(*fp4)(50);
7 m3 e5 D" t% w, |; f$ J# ]
$ w/ n4 G$ Y2 z. V- Y' R) I return
0 a, z3 o: E7 ]# g) U6 }0;9 x) T' g2 Z }" |
}
6 V# T2 U( Z* B- z3 q, i# z/ T, [ I" c0 v
void MyFun(int x) //这里定义一个MyFun函数) Q. g' f7 p! o" ^. \- W
{
/ q2 P2 @' ]3 {# F7 ]% ~% g( l% H printf("%d\n",x);% m9 c1 Z4 ]3 U' N* l, ~! ~7 J3 i
}
% v- b2 o3 H* X" ]$ b# r
5 Z* ^" M0 j/ e6 n: p: m
2 ]( C0 p; l; z. Q' B
- q" V0 u3 o! z3 Y1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。
. y0 Q# S0 u7 n5 u* R1 [2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。* @+ |1 u, q. p1 q0 L
3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。
; X1 g9 t8 K1 Q( p+ x/ X V! ]4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|