函数指针在C++中有着重要的应用,函数的函数名其本质就是代表一个地址,这个地址叫做函数入口,得到这个地址就可以对这个函数进行各种操作。

函数类型基础

  • 函数三要素: 名称、参数、返回值
  • C语言中的函数有自己特定的类型
  • C语言中通过typedef为函数类型重命名,类似于定义数组
typedef type name[m];//定义数组类型
typedef type name(parameter list);//定义函数类型
typedef int f(int, int);
typedef void p(int);

函数指针

函数指针用于指向一个函数

函数名是执行函数体的入口地址

  1. 可通过函数类型定义函数指针: FuncType* pointer;
  2. 也可以直接定义:type (*pointer)(parameter list);

    pointer为函数指针变量名

    type为指向函数的返回值类型

    parameter list为指向函数的参数类型列表
typedef int(FUNC)(int);

int test(int i)
{
return i * i;
} void f()
{
printf("Call f()...\n");
} int main()
{
FUNC* pt = test; void(*pf)() = &f; pf();
(*pf)(); printf("Function pointer call: %d\n", pt(3));
}

函数指针做函数参数

当函数指针做为函数的参数,传递给一个被调用函数,

被调用函数就可以通过这个指针调用外部的函数,这就形成了回调

其本质就是把函数入口地址和函数参数传递给调用函数,也即对函数类型做了限定

int add(int a, int b);
int libfun(int (*pDis)(int a, int b)); int main(void)
{
int (*pfun)(int a, int b);
pfun = add;
libfun(pfun); } int add(int a, int b)
{
return a + b; } int libfun(int (*pDis)(int a, int b))
{
int a, b;
a = 1;
b = 2;
add(1,3)
printf("%d", pDis(a, b));
}

假如int libfun(int (*pDis)(int a, int b))是一个库中的函数,就只有使用回调了,通过函数指针参数将外部函数地址传入来实现调用

函数 add 的代码作了修改,也不必改动库的代码,就可以正常实现调用便于程序的维护和升级

函数指针正向调用

  1. 函数指针做函数参数,调用方式

    被调用函数和主调函数在同一文件中,这种方式在实际开发中并不会用到
  2. 函数指针做函数参数

    被调用函数和主调函数不在同一个文件中、模块中。

    难点:理解被调用函数是什么机制被调用起来的。框架

    框架提前设置了被调用函数的入口(框架提供了第三方模块入口地址的集成功能)

    框架具备调用第三方模块入口函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef int(*EncDataFunc)(unsigned char *inData, int inDataLen, unsigned char *outData, int *outDataLen, void *Ref, int RefLen); int MyEncDataFunc(unsigned char *inData, int inDataLen, unsigned char *outData, int *outDataLen, void *Ref, int RefLen)
{
int rv = 0;
char *p = "222222222222"; strcpy(outData, p);
*outDataLen = strlen(p);
return rv;
} int Send_Data(EncDataFunc encDataFunc, unsigned char *inData, int inDataLen, unsigned char *outData, int *outDatalen)
{
int rv = 0;
if (encDataFunc != NULL)
{
rv = encDataFunc(inData, inDataLen, outData, outDatalen, NULL, 0);
if (rv != 0)
{
printf("func encDataFunc() err.\n");
return rv;
}
}
return rv;
} int main()
{
int rv = 0; EncDataFunc encDataFunc = NULL;
encDataFunc = MyEncDataFunc; // 第一个调用
{
unsigned char inData[2048];
int inDataLen;
unsigned char outData[2048];
int outDatalen;
strcpy(inData, "1111");
inDataLen = strlen(inData);
rv = encDataFunc(inData, inDataLen, outData, &outDatalen, NULL, 0);
if (rv != 0)
{
printf("edf err .....\n");
}
else
{
printf("edf ok \n");
printf("%s \n", outData);
}
} {
unsigned char inData[2048];
int inDataLen;
unsigned char outData[2048];
int outDatalen;
strcpy(inData, "3333");
inDataLen = strlen(inData);
rv = Send_Data(MyEncDataFunc, inData, inDataLen, outData, &outDatalen);
if (rv != 0)
{
printf("func Send_Data err:%d", rv);
return rv;
}
printf("%s \n", outData);
} getchar();
}

函数指针反向调用

利用函数指针实现的一种调用机制

具体任务的实现者,可以不知道什么时候被调用

回调函数是利用函数指针实现的一种调用机制

回调机制原理

  • 当具体事件发生时,调用者通过函数指针调用具体函数
  • 回调机制的将调用者和被调函数分开,两者互不依赖
  • 任务的实现和任务的调用可以耦合(提前进行接口的封装和设计)

需要重新审视 dll和其他第三方厂商 接口之间的关系

  • 动态库可以集成第三方厂商的业务功能
  • 动态库(框架)不经常改动,能兼容后来的业务模型
  • 动态库和第三方业务模型 模块之间 松耦合

动态库变成框架,需要做的工作

  1. 第三方业务入口传进来(回调函数的入口地址传进来)
  2. 加密 解密 业务模型抽象

    实现动态库加密解密业务模型抽象

    通过定义函数指针类型;函数指针做函数参数实现

深入理解C语言-函数指针的更多相关文章

  1. 深入理解C语言函数指针(转)

    本文转自:http://www.cnblogs.com/windlaughing/archive/2013/04/10/3012012.html 示例1: void myFun(int x); //声 ...

  2. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  3. C语言函数指针基础

    本文写的非常详细,因为我想为初学者建立一个意识模型,来帮助他们理解函数指针的语法和基础.如果你不讨厌事无巨细,请尽情阅读吧. 函数指针虽然在语法上让人有些迷惑,但不失为一种有趣而强大的工具.本文将从C ...

  4. “对外部(局部)变量的访问”是C语言函数指针的最大弱点

    1.“对外部(局部)变量的访问”是C语言函数指针的最大弱点 . #include <stdio.h> #include <stdlib.h> /* 结构体定义 */ struc ...

  5. C语言函数指针 和 OC-Block

    C语言函数指针 和 OC-Block 一. C语言函数指针 关于函数指针的知识详细可参考:http://www.cnblogs.com/mjios/archive/2013/03/19/2967037 ...

  6. 这样子来理解C语言中指针的指针

    友情提示:阅读本文前,请先参考我的之前的文章<从四个属性的角度来理解C语言的指针也许会更好理解>,若已阅读,请继续往下看. 我从4个属性的角度来总结了C语言中的指针概念.对于C语言的一个指 ...

  7. c语言函数指针的理解与使用

    1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: A) char * (*fun1)(char * p1,char * p2); B) char * *fun ...

  8. c语言函数指针的理解与使用(学习)

    1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: 1 2 3 A) char * (*fun1)(char * p1,char * p2); B) char  ...

  9. 转·c语言函数指针的理解与使用

    原文出处:https://www.cnblogs.com/haore147/p/3647262.html 1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: 1 ...

随机推荐

  1. 使用Ajax中get请求发送Token时踩的那些坑

    在使用惯了各种牛X的插件以后,在使用原生组件写一些小东西的时候总是有踩不完的坑! 今天就来说一说我使用原生ajax请求时踩得坑: 下面是我的代码: var xmlhttp; if (window.XM ...

  2. JavaScript创建函数的三种方式

    ㈠函数(function) ⑴函数也是一个对象 ⑵函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码) ⑶函数中可以保存一些代码在需要的时候调用 ⑷使用typeof检查一个函数对象时,会返 ...

  3. React-router的使用:标签跳转和编程式跳转

    目录: 1.demo:NavLink 标签跳转 2.标签渲染路由组件时,获取url参数 3.编程式跳转 参考文档 1)https://reacttraining.com/react-router/we ...

  4. P2051 [AHOI2009]中国象棋 大力DP

    状压个啥$qwq$ 思路:大力$DP$ 提交:2次(自信的开了$int$) 题解:(见注释) #include<cstdio> #include<iostream> using ...

  5. Java进阶知识12 Hibernate多对多双向关联(Annotation+XML实现)

    1.Annotation 注解版 1.1.应用场景(Student-Teacher):当学生知道有哪些老师教,老师也知道自己教哪些学生时,可用双向关联 1.2.创建Teacher类和Student类 ...

  6. ZOJ - 4114 Flipping Game

    ZOJ - 4114 Flipping Game 题目大意:给出两个串s,t,n个灯泡的序列,1代表开着,0代表关着,一共操作k轮,每轮改变m个灯泡的状态,问最终能把s串变成t串的方案数. 坤神题解. ...

  7. python-解决pip安装速度慢的问题--豆瓣镜像

    https://www.cnblogs.com/ZhangRuoXu/p/6370107.html https://blog.csdn.net/tianguiyuyu/article/details/ ...

  8. 用javascript来判别回文数

    什么是回文数?通俗的说就是正着读和倒着读都一样的字符串(即使是数字也是可以看成字符串的). 所以下面回文数都是用字符串来表示的,即判断回文数就是对字符串的判断. 举几个回文数的例子: i love u ...

  9. php原生导出简单word表格(TP为例) (原)

      后台: # 菲律宾名单word导出 public function export_word(){ $tids = $_GET['tids']; $userinfo=M("philippi ...

  10. JDK快捷安装,以及详细安装步骤

    一,直接快捷安装 安装JDK之前先打开终端输入以下内容检查是否有JDK环境 java javac java -version 输入完弹出一堆东西就是安装完成了 如果安装可以使用 rpm -qa | g ...