TA的每日心情 | 慵懒 2016-4-21 12:07 |
---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I 累计签到:3 天 连续签到:1 天
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
C中最重要 最难的就是 指针咯!
$ D0 q# @3 c5 R0 Z' F& H& _- a+ r* Z1 ~; f1 h- |
! e p( C: u4 d; D
在学习C++的回调函数机制时有一个关于函数名和函数指针的疑惑,如是就自己研究了下二者的关系。
! g# {! y( \0 K1 S 快速排序的原型:
) P2 {/ b, }8 G1 g void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *));
, }# D& F( w8 ?. i# N' w 可见qsort接受一个类型为_USERENTRY的函数指针fcmp,但是下面代码中qsort函数接受一个函数名,却不是一个函数指针。而函数名和函数指针的关系如何呢?
+ j0 g" ~+ H4 [8 X: x( ^7 c1 ?, | #include <stdio.h>
6 e, t1 F! E5 c. ]#include <stdlib.h>
% F% C: d* b( V1 u- Kint sort_function( const
% |) c& r# i p3 G( M4 }+ Evoid) Z1 l8 F* Z2 a) y4 F& u
*a, const8 j: w- O' h2 k) P. u) } Y
void: {$ S* m# o9 C* B% E
*b); + y. p2 Q# `3 \7 o; @
int list[5] = { 54, 21, 11, 67, 22 }; ( Q3 f G7 e5 b1 T: ]
3 t" C; ], r \1 T. Nint main(void) % i l) F$ p$ j9 P2 z" P
{
" }' x3 a9 V# c: n/ T int x; + B5 ^4 Y7 M% p6 u; [9 m
* G; ]5 L& X4 }% M. b; m
qsort((void g) h; |# X- G" v' T# l, V# A
*)list, 5, sizeof(list[0]), sort_function); N; s8 N7 W# c5 r. ]. W6 e0 m
for (x =- q6 n ^: o' A# h9 x* l6 Y
0; x <
$ x6 x: H0 z4 |9 p) g5; x++)
9 }# @- x6 {. `, V printf("%i\n", list[x]);
0 s( q: Z- s5 D/ @3 u& F. o2 C return& S6 s5 a- _* M: q L+ F" O
0;
4 K4 p: M7 I( Y" x; G}
3 O6 y; ]' U$ T" S3 j5 s, N
5 p( n7 P. v: g+ V K2 `8 \; }int sort_function( const
( l0 r6 O; V# e9 N% K! J0 N1 Bvoid& X: h5 w: z4 H q+ U
*a, const
! x) r% i: i; @$ |6 g6 Kvoid% U5 `. z: v% c6 H! ~& e# E) j
*b)
6 {/ B6 @: X6 o5 }{ 6 o; E! D4 k ]5 r
return; c+ N/ _/ j2 ]7 {
*(int*)a-*(int*)b;
/ D. d! M* K, |6 F. ?- V}5 e5 B4 n1 c3 B3 u# X
- S4 \- i8 U% J4 A) ` M
1 y. T* E! T+ z& E8 [
+ Z1 o5 _! Z: X
函数指针实际上就是该函数代码段开始的地址。其实,编译器对于函数名、函数指针都是转换为一个地址,这个地址就是该函数代码起始地址。
% z0 T6 b- I4 { 下面的代码说明了函数名和函数指针的关系:#include<stdio.h>6 T! w" Q% f' B6 L6 t% [; ^
- E# j$ F/ {: H( w5 N, J! T+ ]0 F
" k+ c" P6 E5 G2 ]void MyFun(int x);0 m7 v( _& K$ T+ K: e
typedef void (*FunP)(int); ; N# Y/ @ J) j' h( P0 v3 c1 l. ?
3 E8 u7 g# Z3 @% r5 y" ]8 bFunP fp1 = NULL, fp2 = NULL, fp3 = NULL, fp4 = NULL ;
' z! @; I" f, z( ~3 y3 d* O" y( x1 P' S, k, Y+ {( @
int main(int argc, char* argv[])( q+ c8 A- E" c6 h, A/ c2 o$ F
{3 P" R+ k; _1 p6 t% x
MyFun(10); //这里是调用MyFun(10);函数$ f5 B/ m) \2 T( K' P7 s
$ s" y9 j; Q* f
fp1=&MyFun; //将MyFun函数的地址赋给FunP变量
; y5 |9 B3 V1 p6 n/ k2 ]- q (*fp1)(20); //通过函数指针变量FunP来调用MyFun函数的。 $ f: _7 B M! a
C) Z E1 o+ @$ l) ]4 E" W% ?
fp2=&MyFun;
5 s4 R5 k, O2 S2 v2 I4 B fp2(30);
3 `8 g& p& L, x' a$ ~# B" X
1 E6 Y5 u: _. }& V. x: L2 A% v fp3=MyFun; , ^+ E4 l) D& U' s
fp3(40); ! s1 Y: K$ U: v
3 b0 L+ s$ W1 G% l8 f
fp4=MyFun;
4 g$ r( l0 M7 B; n# l5 ] (*fp4)(50); , \2 }: T8 t: a* L; a" @1 X4 D
- G$ S+ z1 s" G( b
return5 A! _+ ^' i _; K# B$ R, O
0;: m/ h; E3 k. B: v
}' `& n1 f6 S" y" ]. G9 [
' W! P& v, `( x( ivoid MyFun(int x) //这里定义一个MyFun函数0 ]0 s: _. a( z5 M" S/ K
{
5 A/ q% d: q, t, @+ @$ D printf("%d\n",x);
1 ^; ]. E) [- H6 M, J, X8 ^6 ^}
$ M0 l: D1 T3 ^0 V! ~( M
O% M- _, a! T- J; U9 K/ x0 P2 S+ j5 E6 j; A
- _: H& X7 E* I/ w+ U+ o) Y1. 可见,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。
" @. r# {1 q( o0 O( \2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用 (这样方便多了并与数学中的函数形式一样)。
& R W' ^ o/ V$ g0 F3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。, S" K, F Q. f
4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun |
|