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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
前言/ ^- x, v/ a1 ?) S
函数指针和指针函数,在学习 C 语言的时候遇到这两个东西简直头疼,当然还有更头疼的,比如什么函数指针函数、指针函数指针、数组指针、指针数组、函数指针数组等等,描述越长其定义就越复杂,当然理解起来就越难,特别是刚开始学习这门语言的童鞋,估计碰到这些东西就已经要崩溃了,然后好不容易死记硬背下来应付考试或者面试,然后过了几天发现,又是根本不会用,也不知道该在哪些地方用,这就尴尬了。
2 C, d& B" G2 r; e% _/ x: u今天这里只讲两个相对简单的,其实上面说那些太复杂的东西也真的很少用,即便是用了理解起来很麻烦,所以莫不如先深刻理解这两个比较容易的,并且项目中比较常用到。
( S. B/ ^9 S) `: m
5 I/ k# u, d- t正文
0 h( c3 p, b  E* \8 F) K- h先来看看两者的定义以及说明。
+ C1 T0 ^8 p  i( l6 B3 }$ o. a- o/ T+ y# t
指针函数  }% l4 K* }( S+ J$ G$ [
定义
. Y' Y) _* i' v' a0 a指针函数,简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。
& P' E0 B2 y9 t" `声明格式为:*类型标识符 函数名(参数表)
% }8 J7 O" V+ p" ]4 `7 w5 v
8 m, r& Q8 M6 Y; g这似乎并不难理解,再进一步描述一下。/ a3 g; H1 R' {; F; F; P
看看下面这个函数声明:
; Q' Q0 b; }0 }0 C. u8 q5 ^1 Y9 P8 ]1 E* Z9 K
int fun(int x,int y);5 _+ n4 w4 G% N+ O2 a! O

3 N) P" f5 Q5 ^1 |% n) F" [- {  p这种函数应该都很熟悉,其实就是一个函数,然后返回值是一个 int 类型,是一个数值。. @! B& D# G( I: q+ P8 Y) Q% @, V
接着看下面这个函数声明:
1 F8 K  I# a4 G. S+ S2 H
; w- i. ^+ q  D3 B% Y+ n- k# jint *fun(int x,int y);
- Y# C' d: o' ]1 K! |: {8 h- w" q8 y1 \
这和上面那个函数唯一的区别就是在函数名前面多了一个*号,而这个函数就是一个指针函数。其返回值是一个 int 类型的指针,是一个地址。
0 E; V. D7 Z0 O4 B" s" V" H" b  t1 j2 |, K  @8 b) w* \8 n
这样描述应该很容易理解了,所谓的指针函数也没什么特别的,和普通函数对比不过就是其返回了一个指针(即地址值)而已。
  m. c/ s5 t/ [4 ?9 Q
0 R0 w+ w$ T. t3 |- }  w$ u指针函数的写法: R7 C4 m# p0 q$ t% p
int *fun(int x,int y);6 ~2 S6 r: }: a6 n  b$ V
int * fun(int x,int y);2 p( }- D; f/ M8 y
int* fun(int x,int y);% U; u; A5 X) K" N1 H
! F% ]; l. M7 B+ r+ ^
这个写法看个人习惯,其实如果*靠近返回值类型的话可能更容易理解其定义。
$ n/ ?, ~' j0 a( F
) h5 j7 a( [( T( k6 ~示例/ f2 y5 m, R$ B
(由于本人习惯于 Qt 中进行开发,所以这里为了方便,示例是在 Qt 工程中写的,其语法是一样的,只是输出方式不同)
! r0 r  ]# b- M8 ]! i; C* A来看一个非常简单的示例:3 r6 F1 X3 N- q6 ?

7 }) r* q$ L! v9 F+ A6 ~6 Itypedef struct _Data{5 f4 Y' ^0 s7 k7 ^
    int a;
# n+ l- C* c" Q, ]" \    int b;6 l" o" Z" O. X
}Data;
4 c; C( f3 ?' X8 W/ d- u3 P% L, J. G8 }  `1 G! E3 S* e9 U. C7 A: G) |
//指针函数
$ v6 u* ]% E2 K+ _2 A7 Y! IData* f(int a,int b){/ j' O. Z1 ~/ B7 i! C5 k
    Data * data = new Data;
% ~& }4 w! h+ z% y+ }) ~; p5 `    data->a = a;
7 P( q2 b5 i* B4 W    data->b = b;
9 k( r% ^/ k( t1 ?, V    return data;( n! o: v% s2 m
}
0 Q! m. b" q: Q0 k: c+ H8 A) T( W# W( N! M. r
int main(int argc, char *argv[])4 e  u/ C7 d# j/ `2 _; B
{# M3 P( Q: y# f% }8 M, U+ {
    QApplication a(argc, argv);7 v4 x4 z7 C6 o) D+ m$ S* e+ w
    //调用指针函数# C$ s$ S2 b+ Y, ^
    Data * myData = f(4,5);
' Z3 o8 ?7 P+ j, j2 g    qDebug() << "f(4,5) = " << myData->a << myData->b;
" |+ `0 t: q+ F% t1 f1 b) X+ a2 L+ Y+ {( `3 M+ n8 T: h
    return a.exec();
: z. j3 m6 J' D. p7 I+ B}; V7 z8 b% D. P/ u5 e; y

: I, E8 a5 d9 b$ d, t其输出结果是一样的,不过不建议这么使用,因为强制转换可能会带来风险。
" e5 o0 Q2 h% n
- N; H  V1 p' b函数指针: E* R( n- J. U$ {7 o$ O* G
定义
6 J. a- Q6 l0 f函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。
) P/ R/ e6 F$ V; F* C声明格式:类型说明符 (*函数名) (参数)8 l2 T' ?; f* L: c* t( j: D
如下:3 U8 k" |  d" c; k& N# k

4 j( G+ O0 {0 {7 B7 Tint (*fun)(int x,int y);5 L1 Q7 d: D, y
! ~  x: W9 f. G9 A! b
函数指针是需要把一个函数的地址赋值给它,有两种写法:
/ J% q- Y+ F' l# c) P0 X
# }- a9 e! K6 w' ]* Rfun = &Function;
7 T  j' N, ]% w# x9 K* wfun = Function;/ ?$ C+ a- R5 g' C( W4 y  L
3 _( O+ i; `5 m2 O
取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。6 r- _' g6 {6 m
' U3 X4 H  i: w, H
调用函数指针的方式也有两种:( x6 y( n/ z( @9 E1 h, b7 H
+ d# C4 U! s& ], }% u
x = (*fun)();
/ A- B* R6 T2 X, w( y! F/ L0 ax = fun();% Q4 q1 A* X+ v4 g: t
+ M2 D7 |4 O1 k1 I# T3 L
两种方式均可,其中第二种看上去和普通的函数调用没啥区别,如果可以的话,建议使用第一种,因为可以清楚的指明这是通过指针的方式来调用函数。当然,也要看个人习惯,如果理解其定义,随便怎么用都行啦。& A- {, }8 X' B  S5 V) u0 x
) u* L- |/ r) H4 z; f5 l
示例
0 A# }6 c4 d! a  Vint add(int x,int y){
, K! D' Y$ m0 d0 c4 k/ c* _+ \! u: J2 h    return x+y;6 c' M2 H) a1 D6 M7 F7 i
}9 c3 r. \& X8 g( ^
int sub(int x,int y){
6 p0 Z/ `7 v2 g' H" ~& L$ ]    return x-y;
4 Y1 C. R: Z! p( d+ C) ], i" P6 N}
7 P+ }0 M4 J$ n4 S0 m//函数指针
7 b& ^) h8 {6 U) T; lint (*fun)(int x,int y);. m8 k4 J4 p5 L- S7 Q
% |& _$ O9 d  p& O3 l
int main(int argc, char *argv[])
( J- K$ D$ C1 j+ O. {) l9 x; k4 H, v{3 Q8 j$ D% g. K) N# r2 e
    QApplication a(argc, argv);
7 ]. y0 i6 O! o4 K9 F* b" O( \1 |    //第一种写法: A  }0 X- }6 _; p  r
    fun = add;
6 n1 ?. E4 m" f    qDebug() << "(*fun)(1,2) = " << (*fun)(1,2) ;  o% F/ k5 C1 y. L; P1 |$ O" r
        //第二种写法( _; ]; Q2 x6 f# }: e, U1 U+ q  ?
    fun = &sub;
/ u! \" w: R) l$ K3 {9 [3 l7 ~    qDebug() << "(*fun)(5,3) = " << (*fun)(5,3)  << fun(5,3);
/ Z' }) Q! B# A$ s% d; d
. X; }6 A) e. Y    return a.exec();
2 Y1 m- _1 ?7 q3 E- V5 `}& q7 U* I( E: J+ O$ n. j1 d6 F
% C* _8 j- I; |+ d" x- C; `6 S
! N% F. Q: d: v  J& z
输出如下:$ [" t" O7 n6 H- H7 Q8 m6 T

  \. T' N8 U' a(*fun)(1,2) =  32 C, P: F3 t  X& \3 s
(*fun)(5,2) =  2 2  k# A4 {7 P3 `2 m7 v" r
1 ~1 n4 {* l, g( l2 j8 e$ @
上面说到的几种赋值和调用方式我都分别使用了,其输出结果是一样的。* T& C' d0 u$ K7 n+ s; d& h
: Y) r9 E6 P- ?* I+ H1 r! V
二者区别
) g# i/ Y6 U% u0 U( @通过以上的介绍,应该都能清楚的理解其二者的定义。那么简单的总结下二者的区别:
9 Y: s8 ?9 a2 \# X& M
8 V! ?; f/ i6 I2 ~定义不同3 P( M" s5 \7 p( b& `5 u
指针函数本质是一个函数,其返回值为指针。7 f; M0 F- ~4 z
函数指针本质是一个指针,其指向一个函数。9 N% A9 @' z$ R  i' [; M: t7 |
1 D4 u, L* }# t/ L& P$ M
写法不同
0 S: ^, K) f8 f' a" @指针函数:int* fun(int x,int y);) ^8 F& `; ?9 [/ O( a+ |0 X- T; t
函数指针:int (*fun)(int x,int y);
; T/ \' I5 G/ `/ ?: N  a7 U可以简单粗暴的理解为,指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的。( c. N( [& z! q- J
再简单一点,可以这样辨别两者:函数名带括号的就是函数指针,否则就是指针函数。
0 v' |5 k7 k8 e" I% X" {' h8 V8 @8 r+ }
用法不同/ i' h! {9 B5 N; E1 D
上面已经写了详细示例,这里就不在啰嗦了。' H! L* k; I; g0 e. T# a& o6 u

/ f2 e2 k# o2 o. T6 q) u总而言之,这两个东西很容易搞混淆,一定要深入理解其两者定义和区别,避免犯错。
8 j' [; e; b- s0 U* Z+ K# J2 {. I2 b
: w( u) h' S4 O* b$ K; M1 [. B% R* ?' y* _8 W7 B

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-8-14 05:51 , Processed in 0.109375 second(s), 23 queries , Gzip On.

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

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

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