C/C++ 函数类型、函数指针

1、函数类型语法基础

函数三要素: 名称、参数、返回值

C语言中的函数有自己特定的类型

C语言中通过typedef为函数类型重命名

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));

}

2、函数指针做函数参数

  1. 指针做函数参数pk函数指针做函数参数

回忆指针做函数参数

一级指针做函数参数、二级。。。。、三级

  1. 函数指针做函数参数

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

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

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)  //直接调用add函数

printf("%d", pDis(a, b)); //通过函数指针做函数参数,间接调用add函数

//思考 这样写 pDis(a, b)有什么好处?

}

//剖析思路

//1函数的调用 和 函数的实现  有效的分离

//2 C++的多态,可扩展

现在这几个函数是在同一个文件当中

假如

int libfun(int (*pDis)(int a, int b))

是一个库中的函数,就只有使用回调了,通过函数指针参数将外部函数地址传入

来实现调用

函数 add 的代码作了修改,也不必改动库的代码,就可以正常实现调用

便于程序的维护和升级

回调函数思想:

结论:回调函数的本质:提前做了一个协议的约定(把函数的参数、函数返回值提前约定)

请思考:C编译器通过那个具体的语法,实现解耦合的?

C++编译器通过多态的机制(提前布局vptr指针和虚函数表,找虚函数入口地址来实现)

3、函数指针正向调用

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

被调用函数和主调函数在同一文件中(用来教学,没有任何意义)

2、函数指针做函数参数

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

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

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

框架具备调用第三方模块入口函数

  1. 练习

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();

}

4、函数指针反向调用

回调函数效果展示。

5、C动态库升级成框架案例

C语言版本Socket动态库升级成框架集成第三方产品

简称:C动态库升级成框架案例

名字解释

  动态库:抽象类一个套接口,单独封装成模块,供别人调用;无法扩展。

框架:能自由的扩展

案例背景:一般的企业信息系统都有成熟的框架,可以有C语言写,也可以由C++语言。软件框架一般不发生变化,能自由的集成第三方厂商的产品。

案例需求:在socket通信库中,完成数据加密功能,有n个厂商的加密产品供你选择,如何实现动态库和第三个厂商产品的解耦合。

提醒:C++通过抽象类,也就是面向抽象类编程实现的(相当于C++编译器通过多态机制,已经很好用了。提前布局vptr指针、虚函数表;调用是迟绑定完成。),

C语言中如何实现哪?

案例要求: 1)能支持多个第三方厂商加密产品的入围

2)企业信息系统框架不轻易发生框架

需求实现思路分析

 

思考1:企业信息系统框架、第三方产品如何分层

思考2:企业信息系统框架,如何自由集成第三方产品

(软件设计:模块要求松、接口要求紧)

思考3:软件分层确定后,动态库应该做什么?产品入围厂商应该做什么?

以后,开发企业信息系统框架的程序员,应该做什么?

第三方产品入围应该做什么?

编码实现

  1. 动态库中定义协议,并完成任务的调用

typedef int (*EncData)(unsigned char *inData,int inDataLen,unsigned char *outData,int *outDataLen,void *Ref, int RefLen);

typedef int (*DecData)(unsigned char *inData,int inDataLen,unsigned char *outData,int *outDataLen,void *Ref, int RefLen);

  1. 加密厂商完成协议函数的编写
  2. 对接调试。
  3. 动态库中可以缓存第三方函数的入口地址,也可以不缓存,两种实现方式。

案例总结

回调函数:利用函数指针做函数参数,实现的一种调用机制,具体任务的实现者,可以不知道什么时候被调用。

回调机制原理:

当具体事件发生时,调用者通过函数指针调用具体函数

回调机制的将调用者和被调函数分开,两者互不依赖

任务的实现 和 任务的调用 可以耦合  (提前进行接口的封装和设计)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高亚奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值