C语言_函数指针

2023-11-05

回顾指针概念

	int a, b = 0;
	int* ip = &a;
	int** sp = &ip;

	int ar[10] = {};
	ip = ar;

	int(*par)[10] = &ar;
	int* pbr[10] = {};
	int* (*sbr)[10] = &pbr;
	//需要定义一个指向一维整型数组的指针,才能指向pbr数组

函数指针

//int fun(int, int); //= nullptr错误//函数声明
int (*pfun)(int, int) = nullptr;//函数指针变量的定义
int x = 10;
int y = 20;
int z = 0;
pfun = Add_Int;
z = Add_Int(x, y);
z = pfun(x, y);//新的函数调用规则
z = (*pfun)(x, y);//旧有的函数调用规则


pfun = Sub_Int;
z = pfun(x, y);

上面的代码可以由下面这个图来表示出来
在这里插入图片描述

注意对于函数指针不能计算所指函数的大小,可以计算指针大小

sizeof(pfun);//√
//sizeof(*pfun);//x

函数指针可以作为函数的参数传到函数中

int Add_Int(int a, int b) {
	return a + b;
}

int Sub_Int(int a, int b) {
	return a - b;
}

void fun(int a, int b, int(*pfun)(int, int)) {
	assert(pfun != nullptr);
	int c = pfun(a, b);
	printf("%d\n", c);

}

int main() {
	fun(x, y, Add_Int);
	fun(x, y, Sub_Int);
}


回调函数

函数指针在作为函数参数的时候,可以采用函数声明的方式作为形参,这是一个比较特殊的点,比如下面两个函数参数中函数指针的写法是等价的,虽然这里面的int pfun(int, int)是函数声明,但是确实正确的允许的

void fun(int a, int b, int pfun(int, int)) {
	assert(pfun != nullptr);
	int c = pfun(a, b);
	printf("%d\n", c);

}

void fun(int a, int b, int(*pfun)(int, int)) {
	assert(pfun != nullptr);
	int c = pfun(a, b);
	printf("%d\n", c);

}

回调函数的用处

void* Print_Int(void* p)
{
	int* ip = (int*)p;
	printf("%d ", *ip);
	return ip + 1;
}
void* Print_Double(void* p)
{
	double* dp = (double*)p;
	printf("%lf ", *dp);
	return dp + 1;
}
void* Print_Char(void* p)
{
	char* cp = (char*)p;
	printf("%c ", *cp);
	return cp + 1;
}
void Print_Array(void* br, int n, void * (*fp) (void *) )
{
	for (int i = 0; i < n; ++i)
	{
		br = (*fp)(br);
	}
	printf("\n");
}
int main()
{
	int ar[] = { 12,23,34,45,56,67,78 };
	int in = sizeof(ar) / sizeof(ar[0]);
	double dx[] = { 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9 };
	int dn = sizeof(dx) / sizeof(dx[0]);
	char str[] = { "yhpinghello" };
	char cn = strlen(str);
	Print_Array(ar, in,Print_Int);
	Print_Array(dx, dn,Print_Double);

	Print_Array(str, cn, Print_Char);

	return 0;
}

打印数组,数组类型不同,这个时候可以定义几个不同函数类型的函数,然后在打印数组的函数内传递函数指针参数,使得数组顺利打印出来,这里面就是函数回调的应用,是函数指针泛型函数的应用。

函数指针返回类型

函数指针也可以作为函数返回类型来使用,如下面这段代码,但是由于函数指针如果作为函数返回类型来使用的话,会十分复杂,让人眼花缭乱,所以这里面采用typedef定义函数指针类型,方便了函数指针作为返回类型来使用

typedef int(*PFUN)(int, int);
//typedef int (*)(int, int) SFUN;//error
int (*g_fun)(int, int) = nullptr;
//int(*GetPFun(int (*fp)(int, int)))(int, int)
PFUN GetPFun(PFUN fp)
{
	int (*old)(int, int) = g_fun;
	g_fun = fp;
	return old;
}

函数指针应用例子

输入数字1-7,打印其对应的星期数

void PrintMon()	{printf("Monday\n"); }
void PrintTue() { printf("Tuesday\n"); }
void PrintWed()	{ printf("Wednesday\n"); }
void PrintThu(){ printf("Thursday\n"); }
void PrintFri()	{printf("Friday\n");  }
void PrintSat()	 { 	printf("Saturday\n");}
void PrintSun(){   	printf("Sunday\n");	 }
void (*pfun[])() = { 
	PrintMon,
	PrintTue,
	PrintWed,
	PrintThu,
	PrintFri,
	PrintSat,
	PrintSun 
};

void Print(int i)
{
	assert(i >= 1 && i <= 7);
	(*pfun[i - 1])();	  //pfun[i - 1]();
}
int main()
{
	int message;
	while (scanf_s("%d", &message), message != -1)
	{
		Print(message);
	}
	return 0;
}

在vc 6.0++中有下面这个有意思的情况,可以根据函数指针地址,将其强转为函数对象,然后解引用调用该函数,也能调用成功。如下面这段代码:

void fun()
{
	printf("yhping hello \n");
}

int main()
{
	int a = 10;
	void (*pfun)() = NULL;

	pfun = (void (*)())0x0040b760;

	(*pfun)();

	(*((void (*)())0x0040b760))();

	(*(void(*)())0))();


	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言_函数指针 的相关文章

随机推荐

  • 【java面试常见4】

    文章目录 1 面向对象的特征有哪些方面 2 作用域public private protected 以及不写时的区别 3 String 是最基本的数据类型吗 4 float 型float f 3 4是否正确 5 short s1 1 s1
  • Git操作与仓库创建

    Git简介 首先了解一个概念 版本控制 简单来说就是如果你做文案工作 每次提交之后 你的领导会让你修改 一篇稿子可能修改十几次 但是最后定稿的很可能不是最新修改的那一稿 所以就需要有个版本控制的方法 可以回溯到你所修改的任何一版 并且可以拿
  • ServerletContext

    ServerletContext ServerletContext是一种各serverlet项目间互相传输数据的存储器 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img s29palnw 1613542859309
  • c++基础 STL 第三篇:(deque容器和stack容器)

    文章目录 一 deque 的基本概念 二 deque 的构造函数 三 deque 的赋值操作 四 deque 的大小操作 五 deque 的插入和删除 六 deque 的数据获取 七 stack 的基本概念 八 stack 的常用接口 一
  • 配置文件及日志文件脱敏

    配置文件脱敏 使用原因 在项目中 经常需要在配置文件里配置一些敏感信息 比如数据库用户名和密码 redis mq的连接信息等 如果直接写明文 很容易造成密码泄露等安全问题 jasypt简介 Jasypt是一个Java库 它允许开发者以最小的
  • 文档在线预览(四)使用js前端实现word、excel、pdf、ppt 在线预览

    文章目录 实现方案 一 docx文件实现前端预览 1 docx preview 2 Mammoth 二 PDF文件实现前端预览 1 pdf js 2 pdfobject js 3 vue pdf 4 iframe object embed
  • 【高等数学重点题型篇】——一元函数微分学的应用

    本文仅用于个人学习记录 使用的教材为汤家凤老师的 高等数学辅导讲义 本文无任何盈利或者赚取个人声望的目的 如有侵权 请联系删除 文章目录 一 证明f n
  • [当人工智能遇上安全] 7.基于机器学习的安全数据集总结

    您或许知道 作者后续分享网络安全的文章会越来越少 但如果您想学习人工智能和安全结合的应用 您就有福利了 作者将重新打造一个 当人工智能遇上安全 系列博客 详细介绍人工智能与安全相关的论文 实践 并分享各种案例 涉及恶意代码检测 恶意请求识别
  • unity3d小小白之改变地面的颜色质感

    如果不知道怎么建地面 可以看上一个随笔噢 这样看起来很冰山诶 换颜色呢 要先把unity3d自带的基础素材导入噢 如果你有自己的素材也是可以导入的 只不过要放在assets文件中 最好建个专门的文件夹存放图片 pigPhoto catPho
  • 深入 Spring 系列之静态资源处理

    1 背景 前一段时间 WebIDE 开源的过程中 无意间接触到 webjars 觉得比较有趣 于是研究并整理了一下 webjars 是将前端的库 比如 jQuery 打包成 Jar 文件 然后使用基于 JVM 的包管理器 比如 Maven
  • 键盘控制ElementPlus树形控件展开收起选中功能

    需求 1 当树形控件获取焦点后 可通过键盘上下键来选中节点 2 当存在子节点时 键盘左键展开树 键盘右键收起树 注意 通过上下键来选中数据节点时 只有canFocus为true的节点才能被选中 移动键盘上下键 切换树节点选中项 不执行树的点
  • 记一次APP去壳破解重新打包

    1 拿到apk包时 第一步先判断是否加壳 加的是什么壳 在手机上或者虚拟机上用MT管理器找到对应的apk包 可以看的这个包虽然说是未加固 但还有个伪百度加固 其实也就是加了百度的壳的 2 利用BlackDex32进行去壳 在手机或虚拟机上安
  • 泉州港unityAR方面总结

    环境配置 打包apk环境配置 安装jdk 和安卓SDK 版本要足够高 打开unity 中edit目录下的 首选项 选择SDK和JDK路径 3 Ctrl shift B打开 build Settings选项框 点击选择并转换为Android平
  • Java JDBC 基础

    文章目录 快速入门 使用的步骤 JDBC api 数据库连接的方式 获取驱动的两种方式 获取链接的方式 通过写配置文件来获取链接 tips ResultSet结果集 PreparedStatement 编写JDBCUtils工具类 事务 批
  • 【单片机毕业设计】【mcuclub-308】紫外线消毒灯

    设计简介 项目名 基于单片机的紫外线消毒灯控制系统设计 标准版 基于单片机的室内消毒灯控制系统设计 标准版 基于单片机的智能消毒控制系统设计 标准版 单片机 STC89C52 功能简介 1 通过时钟模块获取当前的时间 并能实现掉电保存时间
  • python下的一些特殊属性(几个实例说明)

    python下的一些特殊属性 几个实例说明 实例1 python view plain copy coding UTF 8 class FirstDemo object 这里是一个doc a 10 类属性 def demo self 第一个
  • NTC热敏电阻温度计算方法,B值法

    1 概述 NTC热敏电阻随环境温度 T 升高 电阻值 会下降 反之 当温度 T 下降 电阻值 会上升 NTC热敏电阻的计算公式有Steinhart Hart方程和B值法两种方法 我只熟悉了B值法 常规NTC热敏电阻参数 温度为 R25 时
  • 一文带你读懂Git中的rebase与fast-forward

    在项目开发的过程中 git作为版本管理工具重要性不言而喻 平常大家肯定会使用merge命令来合并分支 然而merge来合并分支有个缺点 就是当分支太多 合并太多 那么提交记录的图谱看起来就非常丑 以上 而rebase就可以解决这个问题 下文
  • 微电网优化调度

    欢迎来到本博客 作者研究 主要研究方向是电力系统和智能算法 机器学习和深度学习 目前熟悉python网页爬虫 机器学习 群智能算法 深度学习的相关内容 希望将计算机和电网有效结合 本文目录如下 目录 0 摘要 1 引言 2 数学模型 3 算
  • C语言_函数指针

    回顾指针概念 int a b 0 int ip a int sp ip int ar 10 ip ar int par 10 ar int pbr 10 int sbr 10 pbr 需要定义一个指向一维整型数组的指针 才能指向pbr数组