当前位置: 首页 > news >正文

指针(三)

函数指针 

函数指针:存储函数的地址,可以通过这个地址来调用函数。函数指针的声明需要指定函数返回值的类型、函数名(这里用指针名代替)以及函数的参数列表(包括参数的类型和数量)。但是,在声明函数指针时,我们不会给出函数名,而是使用指针名来代替。 

函数指针数组

现在先回忆一下指针数组,它是多个相同变量的地址组成一个指针数组,与函数指针数组有点相像。函数指针数组就是多个相同类型且参数类型也一致的函数组成的函数指针数组。举两个例子吧: 

第一个:下面有fun1和fun2两个函数且返回类型和参数相同,这两个函数的函数指针是这样写的void (*pf)(void)把变量(pf)抛开剩下的就是函数指针的类型【void (*) (void)】。接着说说函数指针数组:它就是再函数指针上加一个方括号[]【数组的表示符】即void (*pf[])(void)它的类型【void (*) (void)[]】。函数的地址和&函数名一个意思,所以加不加都无所谓。最后就是打印,函数指针数组说到底是函数组成的所以调用它是还是需要函数调用符()。

第二个:整数的加减乘除,将加减乘除放在pf[5]函数指针数组里然后直接调用函数指针数组就可以。

指向函数指针数组的指针

指向函数指针数组的指针是一个指针,它指向一个数组,而这个数组的每个元素都是一个函数指针且每个函数指针具有相同的返回类型和参数列表。 

void fun1()
{printf("i like father\n");
}
void fun2()
{printf("i like mother\n");
}
int main()
{void (*pf[2])(void) = { fun1, fun2 };//函数指针数组void (*(*ppf)[2])(void) = &pf;//指向函数指针数组的指针int i = 0;for (i = 0; i < 2; i++){(*ppf)[i]();//*ppf等价于ppf[0]}return 0;
}

下面总结函数指针,函数指针数组和指向函数指针数组的指针三者之间的联系 :

void test(const char* str)
{printf("%s\n", str);
}
int main()
{//函数指针pfunvoid (*pfun)(const char*) = test;//函数指针的数组pfunArrvoid (*pfunArr[5])(const char* str);pfunArr[0] = test;//指向函数指针数组pfunArr的指针ppfunArrvoid (*(*ppfunArr)[5])(const char*) = &pfunArr;return 0;
}

回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数 的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进 行响应。

下面是整数的加减乘除的计算,中间运用了回调函数,对于相同操作且重复使用的可以使用回调函数解决问题。

下面讲通过函数 实现库函数qsort的排序(升序为例)

 qsort对任何类型的数组都能进行排序,由于qsort是库函数所以直接使用就行,但是作为一个计算机专业的学生需要对它有所了解,下面详细说说:

 对于整型数组来说

将数组、数组大小、数组一个元素的字节、一个函数(copy比较相邻元素的大小)这四个参数都写进函数my_sort_int里,这个函数和冒泡排序原理相同,不一样的类型都换成无符号类型,所以可以使用整型或结构体。【my_sort_int(函数名可改变不影响原理)是通用函数】

函数指针将参数强制转换成char*,原因是内存中存放的是十六进制,一个整型是四个字节,对比每个字节的大小。在这个copy函数中返回值分三类(大于、小于、等于0),大于0(说明两个元素为:左>右)为真则进入if语句中,要求为升序则两相邻元素进行交换。

交换则是将内存中的所有数据进行交换,每个字节交换,所以需要知道一个元素有多少个字节(即size)。

对于结构体数组来说 

道理与整型数组相同,就不说了看一下运行的流程。 (my_sort_struct就是通用函数)

最后讲一个:void*什么类型的可以使用,但是不能对这个指针进行与运算【例:假设void* p,不能进行p++(元素的大小不知道,加一不知道跳多远)等】 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • MySQL 数据库自动分区
  • 使用Python恢复Windows、Linux、MacOS回收站中的文件和目录
  • MinIO实战攻略:轻松构建私有云存储解决方案
  • streamlit+wordcloud使用pyinstaller打包遇到的一些坑
  • boost库容器之Circular Buffer功能介绍,及使用示例
  • 神经网络微调技术全解(04)-- Prompt Tuning-可训练提示(Learnable Prompts)
  • 第十章 rust网络编程基础
  • 基于web的停车场管理系统设计与实现-计算机毕设 附源码 16856
  • Kafka·概述
  • 【计算机网络】计算机网络的分层结构
  • 【深度学习与NLP】——深度卷积神经网络AlexNet
  • 华为eNSP:静态路由配置、浮动路由配置
  • 阿里云OSS文件存储
  • 初识C++(8.27)
  • CentOS 7的yum源更换为国内源
  • Docker容器管理
  • ES10 特性的完整指南
  • JS基础之数据类型、对象、原型、原型链、继承
  • Js基础知识(一) - 变量
  • MD5加密原理解析及OC版原理实现
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • python_bomb----数据类型总结
  • spring boot下thymeleaf全局静态变量配置
  • Spring Cloud Feign的两种使用姿势
  • vue数据传递--我有特殊的实现技巧
  • 大型网站性能监测、分析与优化常见问题QA
  • 分享几个不错的工具
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 前端技术周刊 2019-02-11 Serverless
  • 双管齐下,VMware的容器新战略
  • 微信小程序--------语音识别(前端自己也能玩)
  • 详解NodeJs流之一
  • ​520就是要宠粉,你的心头书我买单
  • ‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌
  • #、%和$符号在OGNL表达式中经常出现
  • #Z2294. 打印树的直径
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (C语言)逆序输出字符串
  • (理论篇)httpmoudle和httphandler一览
  • (七)c52学习之旅-中断
  • (七)理解angular中的module和injector,即依赖注入
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (转)shell调试方法
  • (转载)虚函数剖析
  • **《Linux/Unix系统编程手册》读书笔记24章**
  • .gitignore文件_Git:.gitignore
  • .NET 漏洞分析 | 某ERP系统存在SQL注入
  • .net 提取注释生成API文档 帮助文档
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NET连接MongoDB数据库实例教程
  • .NET学习全景图
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @cacheable 是否缓存成功_Spring Cache缓存注解
  • [1181]linux两台服务器之间传输文件和文件夹