找回密码
 注册
关于网站域名变更的通知
查看: 311|回复: 2
打印 上一主题 下一主题

函数指针和指针函数用法和区别

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-11-26 13:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
前言$ n/ K6 ^, K# |( r2 o
函数指针和指针函数,在学习 C 语言的时候遇到这两个东西简直头疼,当然还有更头疼的,比如什么函数指针函数、指针函数指针、数组指针、指针数组、函数指针数组等等,描述越长其定义就越复杂,当然理解起来就越难,特别是刚开始学习这门语言的童鞋,估计碰到这些东西就已经要崩溃了,然后好不容易死记硬背下来应付考试或者面试,然后过了几天发现,又是根本不会用,也不知道该在哪些地方用,这就尴尬了。
' A2 E; H! ~% m0 y6 ^& F+ o, e今天这里只讲两个相对简单的,其实上面说那些太复杂的东西也真的很少用,即便是用了理解起来很麻烦,所以莫不如先深刻理解这两个比较容易的,并且项目中比较常用到。
/ z/ ?& X# q; e( m* X/ h& |1 I! N7 {9 t( ^7 S
正文! H( d4 [2 `" B" }* c0 S& T
先来看看两者的定义以及说明。
# }4 s6 o$ Z& A+ ]4 Q* e' B
1 [* J& T+ w. C8 Z# ?指针函数" t. m9 O, Z: f+ Z" j% Q+ `
定义* o* J7 A- ]& [3 \, ]) B& l
指针函数,简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。
/ |0 t+ C7 `6 l+ Z$ }声明格式为:*类型标识符 函数名(参数表)3 R4 a# Y3 A" d& r5 I! m9 U

7 [- J9 ~1 S% _1 d0 d" l这似乎并不难理解,再进一步描述一下。# n# @5 Q3 n- @* g( U( V0 |
看看下面这个函数声明:
) `( [8 a9 g9 O, U! Q
6 l8 n) L1 X! o. ~3 {6 a; {int fun(int x,int y);4 F8 C+ S3 e- I9 E6 G) u

& H6 n$ Y& D3 h, d5 ?. v这种函数应该都很熟悉,其实就是一个函数,然后返回值是一个 int 类型,是一个数值。
5 `6 _$ w: _& I) ~$ \# q* B7 I. |接着看下面这个函数声明:
0 {1 K6 ^) e* _; ~; v: [, z  h) I8 i9 d5 r
int *fun(int x,int y);$ p& S$ P: X' \7 K9 p

  Q2 }( }0 q  y: a/ x8 K. P! G这和上面那个函数唯一的区别就是在函数名前面多了一个*号,而这个函数就是一个指针函数。其返回值是一个 int 类型的指针,是一个地址。; C0 [- A# l; A7 \  V1 e6 ~! V# ]

( ?6 @6 e# B$ u& q这样描述应该很容易理解了,所谓的指针函数也没什么特别的,和普通函数对比不过就是其返回了一个指针(即地址值)而已。4 D8 M3 M, B) v% ~) p0 K0 a

/ I: o# Y. k& C8 t, T5 j7 ^* C指针函数的写法& ?$ c) r+ F, c8 C8 u
int *fun(int x,int y);4 E/ B+ r" R! z" N# I$ S& J/ p3 c
int * fun(int x,int y);
0 G0 W# `$ m3 H, W7 ~( |1 iint* fun(int x,int y);
, Q3 R* q7 D; \& @1 K0 u( @3 _
, g4 D! b) \$ S3 O4 N# V8 r+ [这个写法看个人习惯,其实如果*靠近返回值类型的话可能更容易理解其定义。9 D. Z4 J! |  h2 `3 x2 f$ F1 a
  ]. @. m1 A* E$ a
示例1 _; G# Y6 O7 S; G* X% X$ b0 I
(由于本人习惯于 Qt 中进行开发,所以这里为了方便,示例是在 Qt 工程中写的,其语法是一样的,只是输出方式不同)
% X. \4 L; G6 M( ~7 n3 u& `1 v3 }来看一个非常简单的示例:
9 {% K, j& S6 U' P# u$ R4 T2 p
3 f- x' t( X' j: l$ d  d/ W. Utypedef struct _Data{0 M; l' Y. q/ d% z1 x+ @# [/ y
    int a;
# r* P2 |/ `) A3 U    int b;
9 f( T- g3 H) R, I7 q}Data;0 Z" S% z6 a6 n, I) g2 t# c  ~$ U
2 G9 a1 m0 N0 s7 ^/ Z+ Z) k
//指针函数
, w( c; z! ]/ J" \Data* f(int a,int b){
' R; z9 e9 s* E6 a    Data * data = new Data;
5 @) s; r2 C, o$ G0 Q    data->a = a;( O) e1 O5 \( |- G) w
    data->b = b;
" `$ c4 G& Y. N  x  y( `% c    return data;- S' c8 c% w5 e! P! ?! }; I, @
}
" g, u0 r7 Z/ E" W' C: }( _
  p7 W- P, ^/ U- U. z, Z% v. yint main(int argc, char *argv[])+ b! e4 |& C% T8 }# n
{
" P# V# V  x' d5 h4 }4 `( Z# c9 O    QApplication a(argc, argv);$ V8 N, {1 h+ k* t
    //调用指针函数
$ R7 M; \+ g' L/ K# i    Data * myData = f(4,5);
% m3 j3 s1 \0 J    qDebug() << "f(4,5) = " << myData->a << myData->b;" F3 \* u8 ?1 b1 O8 Z1 v
: |! s8 W) a9 k( l
    return a.exec();, N. L* c3 I0 U& d' E2 S
}
5 H  h7 q8 r7 f$ }3 P/ s
2 }7 W2 |  h, a- u8 m其输出结果是一样的,不过不建议这么使用,因为强制转换可能会带来风险。
. r, l7 I  H4 V4 v( @6 W. Y. \5 r- O- w* T- g0 O# p3 c
函数指针5 c+ M* s4 z" e
定义
1 q8 X3 z% `3 k  g# q函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。3 v$ B) I0 D+ U" x
声明格式:类型说明符 (*函数名) (参数)" U& w+ o% Y9 |4 o
如下:
5 ?( o; t2 u3 W. ?+ x1 t0 z
7 D7 o1 |6 V6 \( a! lint (*fun)(int x,int y);: O0 C' c' f. `& @: n9 n( x

. |) `$ E0 ]7 t. _. U5 S4 V: O函数指针是需要把一个函数的地址赋值给它,有两种写法:
9 {& O& P. Q8 P  V9 T) |
, v6 j+ R( m% mfun = &Function;; |- \  K8 p  P( d7 {
fun = Function;
7 `$ J: ~9 u3 [6 L% G) v7 G4 q9 r, J0 s, T- m/ _5 ]- h
取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。3 U& u6 f. Q( L# `8 ^

0 z+ U( f: v! h% L调用函数指针的方式也有两种:& c# f/ Z3 |1 ^& H% ]
& K) J3 Z9 b. z" y+ \+ |& R- O
x = (*fun)();; t- o, f# S3 X; h$ i
x = fun();
- y7 m1 z! X+ d% E$ {" Y) ^+ t. d4 X. \7 m, X( _0 O
两种方式均可,其中第二种看上去和普通的函数调用没啥区别,如果可以的话,建议使用第一种,因为可以清楚的指明这是通过指针的方式来调用函数。当然,也要看个人习惯,如果理解其定义,随便怎么用都行啦。( x% T( t5 [1 q3 z( b, U
9 ~( ^) Q! C+ u' W  L# d
示例
5 r9 t0 s# r# C$ m. L; ~( Lint add(int x,int y){$ c) p. b" y4 M( o# c% Y6 S
    return x+y;
0 b. x  E7 F9 Q5 S+ k0 M, U# _8 Y}4 e3 h% Q+ p/ P2 A  Q. u$ W4 C
int sub(int x,int y){3 k. m  ~/ {+ b1 w7 o* y1 H
    return x-y;) p7 i9 R. z( \2 x# }
}
9 _& J/ R0 }. T8 g  t8 S8 k1 r. z//函数指针$ s8 l* C5 ?- A
int (*fun)(int x,int y);* ], g/ h/ l9 d5 b% W; e9 e% _; Y

- `8 h% m+ E0 h% B8 P) P4 V; C/ Eint main(int argc, char *argv[])
* O; c7 I' d/ s( y6 q7 {3 `{0 ^) H$ U. P3 E9 S  e! D) |
    QApplication a(argc, argv);
8 {+ {) }. B* H    //第一种写法
( b! W0 F5 S- j& b" R% `2 n    fun = add;5 F3 W; Z% M2 a( ?: F. c% s
    qDebug() << "(*fun)(1,2) = " << (*fun)(1,2) ;
  ^# \; b% J; k5 G: S        //第二种写法2 y, w6 n. q* m8 O
    fun = &sub;- {; u# e% }/ M! W7 Q# u" h
    qDebug() << "(*fun)(5,3) = " << (*fun)(5,3)  << fun(5,3);
5 v7 Y3 F; y7 p5 ?3 D: s6 E4 E; i3 t- S% Q" _9 p
    return a.exec();
! _8 m* H* ?; X# ^2 w}+ [, o; b/ U" D

( t1 W9 N9 }. n5 ]7 u& ?
% Y+ X1 a$ e! u. f2 s/ h3 `输出如下:6 D0 C: W7 n  J6 Y/ p" S

8 t/ I! V+ A+ c(*fun)(1,2) =  38 G  X" W2 [2 Q$ r8 U0 z
(*fun)(5,2) =  2 22 y1 m7 {8 k. h' |0 P  L

  B, C) U4 l+ Y上面说到的几种赋值和调用方式我都分别使用了,其输出结果是一样的。
% H6 _$ A3 M# c2 O
" \, Q4 z7 y: ^6 c) v二者区别; _  p1 y$ a6 J% z% y9 H
通过以上的介绍,应该都能清楚的理解其二者的定义。那么简单的总结下二者的区别:$ D! k5 b2 i2 ^( Q( G  x7 t6 J' h
( X7 `" O+ T" L- A' q5 h4 \
定义不同
* v* I" `5 J% E! H4 ~! u" l指针函数本质是一个函数,其返回值为指针。
1 S9 f% u/ i0 Y  j6 r: q. V6 K函数指针本质是一个指针,其指向一个函数。
) y) Y6 F2 n/ ~3 y3 ]( B/ y( h. h
# b9 a+ @. }4 \/ n  |. m, K' W  k) d写法不同: s) `* s7 I# J* g. i- [* V
指针函数:int* fun(int x,int y);
# S" R5 f+ z: b$ Y& h' X  [函数指针:int (*fun)(int x,int y);2 ^4 o# S4 t# d% k( U, r
可以简单粗暴的理解为,指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的。, X. \# z1 s/ U; y" n
再简单一点,可以这样辨别两者:函数名带括号的就是函数指针,否则就是指针函数。* n8 \% m1 r; I+ g! m

/ Z' W& |& W  ^8 q# R用法不同
% `) i) H. o' h% Z" z7 w3 G上面已经写了详细示例,这里就不在啰嗦了。
( v, q, s3 F/ K$ i/ ~4 N/ ~  x3 V7 k6 ?
总而言之,这两个东西很容易搞混淆,一定要深入理解其两者定义和区别,避免犯错。
1 M  s& b+ v& K4 J. ^8 N5 A/ r
2 C- Z, v+ b3 B0 K% ?5 n
8 q  c, f' Q: t

该用户从未签到

2#
发表于 2021-11-26 15:06 | 只看该作者
指针函数,简单的来说,就是一个返回指针的函数

该用户从未签到

3#
发表于 2021-11-26 16:09 | 只看该作者
函数指针,其本质是一个指针变量,该指针指向这个函数
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-11-4 11:07 , Processed in 0.156250 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表