TA的每日心情 | 慵懒 2016-4-21 12:07 |
---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!
1 G: o: j d. U4 w0 b1 k' b. f
9 w- ?0 `" r6 k9 Q' Q3 M. y; Q# m- ]- e% v4 ~. c' i- g
在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
' L: l6 O. T+ b, {$ O& f 快速排序的原型:
9 Z7 E: C( [9 p7 x9 U1 t6 \) c void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *));
9 O9 Q- Y! S" R- t5 j 可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
4 F! X' M: n3 T/ J1 { z #include <stdio.h> 1 ^5 s9 t( J2 ]/ q# f( ~; ]
#include <stdlib.h>
. ~1 f* h- [; _4 k9 p; wint sort_function( const0 } Y4 q; [5 C% s4 Z5 s8 H: }
void: n1 B5 T/ C% D6 {9 L
*a, const/ k# l5 K; @, |( \# F5 p7 ~
void
+ o$ A* | b2 I*b); / _8 @4 N8 Z G5 x" l" g( i0 D
int list[5] = { 54, 21, 11, 67, 22 }; 0 A' {# _0 n# u8 B! `/ O
# J" s& [$ V1 U" \% F& i
int main(void) ' ?4 C; g' C/ U. T, A- F
{ % f! e4 L, F5 H
int x; 0 Z; O0 P4 q, t3 E N8 Q0 s3 x. v
5 J- `# F! k# F qsort((void
# `' |, j7 [% e4 c% g9 e7 A*)list, 5, sizeof(list[0]), sort_function);
( B. h$ o4 G3 F0 z% B: @( d- D for (x =1 p$ _: C/ m6 M) i; t8 [, m& j
0; x <
2 }1 J( [. |/ f& A! v3 _, `5; x++)
) D& g! C5 i- g* [) ~6 O5 d5 E printf("%i\n", list[x]); $ G$ e: q' X! q* V X
return1 i- s5 b1 T& H/ B. y6 i9 E& Y" W) \
0; : w4 d& ?) W; d( x
} % n3 q, N! c! ?1 h7 ?' Q2 {0 X
5 K0 ^1 g( h2 S7 _: H
int sort_function( const
( z' _- v+ ~. ?5 M* rvoid
, P% m+ n: g$ N2 ~0 p*a, const
, c$ L+ I8 M8 I2 C }2 g) Lvoid* l; o# B9 U( ?' y: K' q/ A( z
*b)
0 v3 u J! I5 ?0 N/ i( z r{
6 t; t. w+ Z7 p2 {' @ return
1 W# M. F& X' R" T*(int*)a-*(int*)b; + \6 D- z- m3 m/ e" }
}+ Y( V* w, ~4 V& Z# E5 S3 g# l
5 V# _$ v9 v. q# @8 x( d; M( H! x: d0 f \
2 d2 {/ ]3 g' E q1 u% r3 O0 E5 ]3 _
函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。* n( o0 ]" P& s$ j+ Y5 h3 ^; z) h! u
下面的代码说明了函数名和函数指针的关系:#include<stdio.h>
$ @4 Z6 G( _6 m; q: C) R2 R" S6 `
/ C! O- R/ E" o( q. e
void MyFun(int x);$ K) j+ {! ]1 o9 `5 o
typedef void (*FunP)(int); : t6 y4 A$ m6 {
( B3 w. _6 p _# b! RFunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;
5 J7 v! ~/ E5 H) t
% A7 w1 {# V8 [( S! dint main(int argc, char* argv[])
& ^2 |7 k* q5 x+ k' s0 w{9 k: G) s1 }- ^; ~
MyFun(10); //这里是调用MyFun(10);函数
4 I- h8 K. a+ s; b1 f7 B8 T, v
: k6 |7 U) i& T4 z1 ~" T t- [ fp1=&MyFun; //将MyFun函数的地址赋给FunP变量; ~6 D ]# J5 i. M% X
(*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。
+ A! p& d1 d- c$ p, ~" S
: e+ _$ d! k1 H: f$ o3 j* U3 w! P fp2=&MyFun; - h# I* _! x6 e! W' o
fp2(30);
9 l0 ]; B! q) a L2 u$ T5 d- z3 m
fp3=MyFun;
2 P, @0 d2 ~1 u fp3(40); / r+ E! X* u* A% X1 w. I& v, z
+ |+ M# c: V) i0 L. |
fp4=MyFun; " A4 e. [/ z% p f& [2 D& v
(*fp4)(50); ! Q9 e; N; u* }" R
$ F* P# k; d, `! U& E! E* g. Z return
; d! H& f" |# J' P3 i I% v0;
' ^1 [! ?4 \9 {$ Q- B; M. [}! Y# v6 E) e4 y2 @5 @/ v
]7 x% R: E U6 q) I
void MyFun(int x) //这里定义一个MyFun函数
( h" F: O) Q. X5 i6 e6 c5 g{; j. y* f8 s' n8 W. i
printf("%d\n",x);
' M& o' W5 Q- h3 _}6 A! T+ T2 y. v" Q$ u
: O7 Z) E1 q3 z, A4 c8 u( }9 K
; e/ P3 h/ ^% u+ m3 f9 F4 B
7 ^2 s5 u9 G2 Z4 D! [
1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。. O' V& T$ G/ V1 t
2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。/ ]0 t- n9 Q( T
3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。
% A7 ?2 b/ n& B/ X% Z) R% [4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|