01、函数指针

1.1、函数指针定义

一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。

简言之:函数指针其实就是一个指针变量,代表着一段内存。

1.2、函数指针的定义形式

returnType (*pointerName)(param list);

returnType 为函数返回值类型,pointerName 为指针名称,param list 为函数参数列表。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。

返回类型(*函数名)(参数表)

例如下面两种写法都是正确的。

「写法一:」

void (*F_TYPE)(int nParam,char strName); //带参数变量名

「写法二:」

void (*F_TYPE)(int,char); //不带参数变量名

注意事项:注意( )的优先级高于*,第一个括号不能省略,如果写作returnType pointerName(param list);就成了函数原型,它表明函数的返回值类型为returnType*

1.3、函数指针与typedef

想必大家都能看出来,函数指针的定义是很长一段的,如果每次是用都要写这么长一段,额,大可不必,因为,typedef能够解决这个问题。

typedef:程序中的作用一般是取别名,例如下面这个例子,我们把函数指针换个名字。

typedef 返回类型(*新类型)(参数表)

//1.默认原始写法:
void callbackint(int a, int b, int (*pMsg)(int a,int b));
//2.typedef优化后:
typedef void (*PSM)(int a, int b);
void callbackint(int a, int b, PSM p);

这样做的好处是,以后只要需要使用int (*pMsg)(int a, int b)的地方我们都能使用PSM p这种方式来替换他。

typedef是C语言基础,这里不浪费时间在关键字上面,感兴趣的可以自行了解一下。

02、回调函数

2.1、回调函数定义

百度给的解释是:

回调函数就是一个被作为参数传递的函数。在C语言中,回调函数只能使用函数指针实现,在C 、Python、ECMAscript等更现代的编程语言中还可以使用仿函数或匿名函数。回调函数的使用可以大大提升编程的效率,这使得它在现代编程中被非常多地使用。同时,有一些需求必须要使用回调函数来实现。最著名的回调函数调用有C/C 标准库stdlib.h/cstdlib中的快速排序函数qsort和二分查找函数bsearch中都会要求的一个与strcmp类似的参数,用于设置数据的比较方法。

关于名词仿函数,请参考STL源码剖析中的算法一块儿,会有非常细致的解释。

我自己的理解就是:通过参数将函数地址传入,在多线程中,如果主线程在执行此函数时,通过参数中的函数地址,相当于异步执行了另外一个函数,另外一个函数也就是我们所称的回调函数,回调函数多用于socket、http等协议中的消息交互处理,回调函数的本质就是C/C 中的函数指针,如上所述。

2.2、回调函数的使用场景

著名的 lone wolf 曾经解释过这个问题:

其实回调就是一种利用函数指针进行函数调用的过程. 为什么要用回调呢?比如我要写一个子模块给你用, 来接收远程socket发来的命令.当我接收到命令后, 需要调用你的主模块的函数, 来进行相应的处理.但是我不知道你要用哪个函数来处理这个命令, 我也不知道你的主模块是什么.cpp或者.h, 或者说, 我根本不用关心你在主模块里怎么处理它, 也不应该关心用什么函数处理它…… 怎么办? 使用回调!

什么是回调函数?

回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定。在__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或引用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出。理解回调函数!

在很多第三方库中,比如libcurl中:

CURL_EXTERN curl_easy_setopt(CURL* curl,CURLoption option, ...);

就是用了回调函数,通过设置一个函数地址,当我们将内容发送到http请求页面之后,页面会通过字节流返回一个stringstream类型数据,里面就是我们请求服务器之后的返回结果,在一些频繁请求中,你不可能做到每一个都要程序停下来处理,这个时候,就可以使用回调函数来处理,异步通讯。

多线程中:主线程收发数据、子线程处理响应数据。大致都是一个意思。

03、实例重释

我这里分文件举一个简单的例子阐述刚才上面说到的内容。可能内容不够精炼,大佬请随意,初学者建议看一下,很好理解。

功能:创建一个函数,传递两个int类型参数,通过回调函数返回其两个int类型参数的计算结果。

CallBack.h内容如下:

#ifndef _CALLBACK_H
#define _CALLBACK_H//使用typedef进行简化代码,按部就班的写肯定没问题
typedef int (*PMSGMessage)(int a, int b);//回调函数
int callbackInt(int a, int b, PMSGMessage p); #endif

CallBack.cpp内容如下:

#include
#include "CallBack.h"using namespace std;int callbackInt(int a ,int b, PMSGMessage p)
{//回调函数实现retrun p(a,b)
}

test.cpp函数内容如下:

#include
#include "CallBack.h"
using namespace std;int Multiplication(int a, int b)
{//参数检查(避免出现0)if( a == 0 || b == 0){cout << "其中有参数为0,结果应避免为0" << endl;return 0;}return a * b;
}int main()
{int n = 6;int m = 11;int bRet = callbackInt(n,m,add);//如果我们用了类,就是函数等都是成员函数,我们这里要带上域操作符(" :: ")cout << "回调函数执行的结果是:" << bRet << endl; system("pause");return 0;
}

小结:回调函数的简单应用大概就是这么多,如果有机会,建议多用点开源库,那里面很多地方都是用了回调函数机制,而且都是比此例子高级一点的用法,但是基本思想都一样,不要因为用法高级一点就害怕了,自己写两个例子之后,想必对于回调会有更深的理解。

来源:

https://blog.csdn.net/m0_43458204/article/details/116715045

【C/C 】浅谈C/C 中函数指针与回调函数相关推荐

  1. c语言键盘回调函数键盘的码,深入浅出剖析C语言函数指针与回调函数(三)

    前面两篇文章: http://blog.csdn.net/morixinguan/article/details/65494239 http://blog.csdn.net/morixinguan/a ...

  2. 【C语言进阶深度学习记录】三十二 函数指针与使用函数指针实现回调函数

    回调函数是非常重要的概念 文章目录 1 函数的类型 2 函数指针 2.1 函数指针的使用 2.2 使用函数指针实现回调函数 3 总结 1 函数的类型 跟以前学数组的时候是一样的,C语言中的数组是有自己 ...

  3. 函数指针与回调函数详解

    函数指针与回调函数详解 1.什么是函数指针? 函数(的)指针就是指针.这个指针存放一个函数的地址,而函数的名称就该函数的入口,即地址.这类似于数组名就是数组的首地址.我们可以通过反汇编直观的查看到函数 ...

  4. 函数指针与回调函数、句柄

    函数指针 定义: 函数指针是指向函数的指针变量. 因而"函数指针"本身首先应是指针变量,只不过该指针变量指向函数.这正如用指针变量可指向整型变量.字符型.数组一样,这里是指向函数. ...

  5. 网络编程之 信号捕捉器(函数指针与回调函数)

    接着我们的信号说下去      之前博主给大家分享到了信号的概念和初步介绍signal函数的形式后就没有继续往下介绍了,实在是因为时间不够,那个时候博主还要上课,现在博主放假了就好好给大家分享一下如何 ...

  6. 函数指针实现回调函数

    首先说明是函数指针,函数指针,就是一个函数,将其函数名指针化,通过传入指针调用不同的函数 手撸代码一次 #include<stdio.h> void max(int a,int b) { ...

  7. c语言函数指针封装函数,C语言之函数指针、回调函数的使用

    一.背景 首先看下如下代码,这个定义是放在头文件的,在程序中tCdrvCallbackFkt也定义了另一个变量,而且括号后面还跟定义了几个变量,不理解这个定义. typedef void (PUBLI ...

  8. 函数指针和回调函数的简单应用

    文章目录 前言 函数指针的简单应用 什么是回调函数? 利用冒泡排序实现qsort函数 前言 本博客主要记录一些函数指针和回调函数的简单应用: 函数指针的简单应用 上一篇博客我记录了什么是函数指针? 那 ...

  9. C语言中函数指针和回调函数的详解

    函数指针:指向函数的指针变量. 因此"函数指针"本身首先应是指针变量,只不过该指针变量指向函数.这正如用指针变量可指向整型变量.字符型.数组一样,这里是指向函数.如前所述,C在编译 ...

最新文章

  1. [Dnode]基于Node.js给浏览器提供异步远程方法调用
  2. bio linux 创建_不断升级,Java之BIO、NIO、AIO的演变
  3. 基于tomcat5.5的数据库连接池环境设置
  4. 终端如何粘贴快捷键_11 个“原来可以这样”的 Linux 终端命令
  5. go语言mysql删除记录_MySQL数据库删除操作-Go语言中文社区
  6. Windows 10重装系统时,提示Windows只能安装到GPT磁盘的解决方法(更新于2021.4.28)
  7. php绕过验证,PHP-Nuke绕过识别码验证漏洞
  8. iPhone Instruments工具使用_检测内存泄露(转)
  9. 天锐绿盾技术大讲堂:终端出现红色“+”
  10. 【现代信号处理】 15 - 谱分析基础和周期图谱分析
  11. 难以忽视的真相:谈及利润,iPhone‘独孤求败’
  12. Java - constants
  13. JavaServer Faces 2.0 can not be installed解决方案
  14. 简单三步轻松恢复Mac电脑丢失的文件
  15. 【算法学习笔记】65. 双向扫描 SJTU OJ 1382 畅畅的牙签盒
  16. 【CV】ViT:用于大规模图像识别的 Transformer
  17. Gitlab访问突然出现 403 forbidden解决方案
  18. html 5 触摸屏事件
  19. 飞利浦SHL3565耳机套耳罩更换
  20. pch有以下几个作用

热门文章

  1. 扩展枚举功能的两种方法
  2. java jpa 规范_Java:在JPA中使用规范模式
  3. 生产替代物料_一种替代的多生产者方法
  4. Java代码样式运算符换行格式
  5. Java 9模块系统(拼图)@ LJC的HackTheTower
  6. 使用jstat的JVM统计信息
  7. eclipse pmd使用_使用您自己的规则在Eclipse中自定义PMD
  8. glassfish发布应用_Arquillian 1.0.0.Final正式发布! 准备使用GlassFish和WebLogic! 所有虫子死亡!...
  9. Java的5个古怪问题
  10. 将java.util.concurrent.BlockingQueue用作rx.Observable