打印
[软件资料]

C语言的回调函数原来这么简单

[复制链接]
334|42
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cr315|  楼主 | 2023-8-9 10:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

了解开发语言的朋友应该都会对回调函数有所了解,在很多的程序开发语言中都能看到回调的身影。很多场景下,当某个条件成立以后我们**代码执行某些指定的部分,这个时候可以考虑使用回调函数的方式,这样做思路更加的清晰,也能使代码结构的逻辑更加清晰,结构更加好。

那回调函数的到底是什么呢?它又是怎么实现的呢?

这是本次想要简单分析的一个主题。

但是在说回调函数之前,我觉得很有必要先说明一下 “函数指针” 这个概念,它是回调函数能够实现的重要基础。

1、函数指针

学习过C语言的伙伴都知道,C语言中的灵魂 — 指针。可以毫不犹豫的说,要检验你对C语言的掌握程度,那指针绝对是最好的考察方式。指针的使用和变幻方式,真正的使用起来能让你眼花缭乱。

下面是常见的指针的定义:

  • int *ptr1;
  • char *ptr2;
  • struct std *ptr3; // 结构体指针



那函数指针到底是什么呢?

函数指针:函数指针是指向函数的指针变量。简单理解是指向函数名的指针变量。

函数指针既然是指向函数的,那么它就可以像函数一样,用于调用函数、传递参数等操作。函数指针的定义方式如下:

  • 函数返回值类型  (* 指针变量名) (函数参数列表);
  • “函数返回值类型”:表示该指针变量可以指向具有什么返回值类型的函数;
  • “函数参数列表”:表示该指针变量可以指向具有什么参数列表的函数。
  • 举例如下:
  • int (*func1)(void)
  • int (*func2)(int,char,...)
  • char (*func3)(int,char,...)
  • ......



从上面的演示可以看到,函数指针的定义就是将一个函数中的 “函数名” 改成“(* 指针变量名)”的方式,从而实现了一个函数指针的定义。

但是这里需要注意的是:“(* 指针变量名)”两端的括号是必须要有的,如果缺少了这对括号,那么这个定义的方式就会变为指针函数。如下:

  • int *func1(void)
  • int *func2(int,char,...)
  • char *func3(int,char,...)
  • ......
  • 这种就不是函数指针了,而是指针函数。两者差别是很大的。



特别需要需要注意的一点是:指向函数的指针变量没有 ++ 和 -- 运算。

对于函数指针,一般为了方便使用,我们会选择另外的一种定义方式:

typedef  函数返回值类型  (* 指针变量名) (函数参数列表);
比如:
  • typedef int (*Fun1)(int,...);
  • typedef int (*Fun2)(int, int,...);
  • typedef void (*Fun3)(void);
  • typedef void* (*Fun4)(void*);
  • ......



使用特权

评论回复
沙发
cr315|  楼主 | 2023-8-9 10:49 | 只看该作者
2.、函数指针的使用方式
清楚了函数指针是什么东西了之后,那函数指针要怎么使用呢?看下面的例子:

/* 1.首先定义一个函数 */
int Func(int x);
/* 2.然后定义一个函数指针 */
int (*p) (int x);
/* 3.将Func函数的首地址赋给指针变量p */
p = Func;

p = &Func;
/* 4.然后使用p调用Func函数 */
(*p) (int x);


因为函数名 Func 代表函数的首地址,所以经过赋值以后,指针变量 p 保存的就是Func的函数入口地址,即 p 就指向函数 Func() 代码的首地址。

为了加深函数指针的使用方式,看下面的一段代码你就明白了。如下:

#include <stdio.h>
int Max(int, int); //函数声明
int main(void)
{
    int a, b, c;
    int(*p)(int, int); //定义一个函数指针
   
    p = Max; //把函数Max赋给指针变量p, 使p指向Max函数
   
    printf("please enter a and b:");
    scanf("%d %d", &a, &b);
    c = (*p)(a, b); //通过函数指针调用Max函数
    printf("a = %d\nb = %d\nmax = %d\n", a, b, c);
    return 0;
}
int Max(int x, int y) //定义Max函数
{
    int z;
    if (x > y) z = x;
    else z = y;
        
    return z;
}


特别注意的是,因为函数名本身就可以表示该函数地址(指针),因此在获取函数指针时,可以直接用函数名,也可以取函数的地址。

p = Max 可以改成 p = &Maxc = (*p)(a, b) 可以改成 c = p(a, b)
3. 函数指针可以作为函数的参数来使用
函数指针变量本身也是一个变量,也可以作为某个函数的参数进行使用的。如下:

#include <stdio.h>
#include <stdlib.h>
// 定义一个函数指针类型的 FunType
typedef void(*FunType)(int);
void myFun(int x);
void hisFun(int x);
void herFun(int x);
void callFun(FunType fp,int x);
int main()
{
    callFun(myFun,1000);//传入函数指针常量,作为回调函数
    callFun(hisFun,5000);
    callFun(herFun,4700);
    return 0;
}

使用特权

评论回复
板凳
cr315|  楼主 | 2023-8-9 10:50 | 只看该作者
4、回调函数
前面讲了函数指针,现在终于到了回调函数了。到这部分,我们就不说太多的废话,直接阐述回调函数是什么,回调函数要怎么使用,一步到位吧!

回调函数:如果一个函数的指针(函数名或地址)作为参数传递给另外一个函数,当这个指针被用来调用其所指向的函数时,就说这个指针所指向的函数是一个回调函数。

再简明点说:回调函数不是直接调用该函数进行使用的,而是要通过另外的特定事件或者其他函数进行调用的,才能称作回调函数。定义一个函数然后直接调用,都不能称为回调函数。

回调函数的定义方式和使用,直接通过下面的例子说明,相信大家一看就会明白。

例程1:
/* 回调函数 */
int Callback(void)
{
    return 0;
}
int Library(int value,int (*MycallBackFunc)(void))
{
    if(value == 1)
        MycallBackFunc();
    else
        return 1;
}
int main()
{
    Library(1,Callback);    // 返回值为 0
    return 0;
}

例程2:
int Callback_1(int a) // 回调函数1
{
    printf("Hello, this is Callback_1: a = %d ", a);
    return 0;
}
int Callback_2(int b) // 回调函数2
{
    printf("Hello, this is Callback_2: b = %d ", b);
    return 0;
}
int Callback_3(int c) // 回调函数3
{
    printf("Hello, this is Callback_3: c = %d ", c);
    return 0;
}
int MyHandle(int x, int (*MyCallback)(int))
{
    MyCallback(x);
}
int main()
{
    MyHandle(4, Callback_1);
    MyHandle(5, Callback_2);
    MyHandle(6, Callback_3);
   
    return 0;
}
从上面的代码可以看出,MyHandle() 函数的参数有一个指针,在 main() 函数里调用MyHandle() 函数的时候,给它传入了函数 Callback_1()、Callback_2()、Callback_3() 的函数名,这时候的函数名就是对应函数的指针,也就是说,回调函数其实就是函数指针的一种用法。

到处,通过上面的函数指针的说明和回调函数的示例代码,估计看到这里的朋友应该都明白了回调函数的使用了吧!

使用特权

评论回复
地板
小夏天的大西瓜| | 2023-8-26 22:41 | 只看该作者
回调函数其实就是函数的使用以及触发

使用特权

评论回复
5
星辰大海不退缩| | 2023-8-27 09:05 | 只看该作者
回调函数一般都是封装好的,很好使用

使用特权

评论回复
6
tpgf| | 2023-9-6 10:55 | 只看该作者
回调函数支持函数之间的嵌套调用吗

使用特权

评论回复
7
nawu| | 2023-9-6 11:26 | 只看该作者
回调函数是指 使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数

使用特权

评论回复
8
zljiu| | 2023-9-6 11:53 | 只看该作者
回调函数主要结构有三部分组成:主函数、调用函数和被调函数

使用特权

评论回复
9
tfqi| | 2023-9-6 12:14 | 只看该作者
回调函数可以将耗时的操作隐藏在回调方,不影响实现方其它信息的展示

使用特权

评论回复
10
gwsan| | 2023-9-6 21:31 | 只看该作者
调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数

使用特权

评论回复
11
aoyi| | 2023-9-6 22:22 | 只看该作者
简单来说,当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数。

使用特权

评论回复
12
vivilyly| | 2023-9-9 16:45 | 只看该作者
C 语言中的回调函数实际上是一种函数指针的使用方式,可以实现灵活的函数调用和参数传递。

使用特权

评论回复
13
wwppd| | 2023-9-9 17:00 | 只看该作者
C语言的回调函数非常简单,它可以用于实现回调功能,通过函数指针将回调函数作为参数传递给另一个函数,并在另一个函数中执行特定的操作。

使用特权

评论回复
14
jonas222| | 2023-9-9 17:09 | 只看该作者
在实际应用中,回调函数的使用可能会更为复杂,但这个简单示例可以帮助您理解 C 语言中回调函数的基本原理和用法。

使用特权

评论回复
15
wangdezhi| | 2023-9-9 17:16 | 只看该作者
回调函数的使用可以使代码更加灵活和可重用。通过将函数作为参数传递,我们可以实现更高级的编程技巧

使用特权

评论回复
16
sanfuzi| | 2023-9-9 17:24 | 只看该作者
C语言中的回调函数原理相对简单。回调函数是一种通过函数指针将一个函数作为参数传递给另一个函数的机制。在C语言中,函数指针可以作为参数传递给其他函数,并在需要的时候被调用。

使用特权

评论回复
17
hudi008| | 2023-9-9 17:32 | 只看该作者
要使用回调函数,首先需要定义一个函数指针类型,然后定义一个函数,该函数的参数是函数指针类型。在需要使用回调函数的地方,可以将一个函数的地址传递给该参数,从而实现回调功能。

使用特权

评论回复
18
wengh2016| | 2023-9-9 17:42 | 只看该作者
回调函数(Callback)是一种常见的编程模式,用于在主函数中处理一些异步操作的结果

使用特权

评论回复
19
lzbf| | 2023-9-9 17:50 | 只看该作者
回调函数是一种特殊的函数,它可以作为参数传递给另一个函数,用于在另一个函数中执行特定的操作。

使用特权

评论回复
20
jtracy3| | 2023-9-9 17:59 | 只看该作者
回调函数可以被传递并在其他函数中灵活调用,使得代码更加模块化和可扩展。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1196

主题

3012

帖子

0

粉丝