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

C语言之函数指针

函数指针的应用

1、函数指针可以指向具有相同签名的函数。

2、函数指针可以作为参数传递给其他函数,从而实现回调机制。

3、函数指针数组可以用于存储多个函数,并通过索引调用它们。


函数指针:
指向的是函数,存的是函数的入口地址

函数指针的好处:
如果赋给不同的函数,我就能够执行不同的函数,使用灵活。

函数指针数组
函数指针数组是一个保存若干个函数名的数组
一般形式如下
<数据类型>(*<函数指针数组名称><大小>)
数据类型:指向的函数的返回值的类型
<大小>:是指函数指针数组元素的个数
其他同普通的函数指针


在C语言中,不但有指向变量或数组的指针,还有指向函数的指针

为什么函数也会有指针呢?
因为一个函数的代码也是存储在一段连续的内存空间中,而这段内存的首地址就是该函数的指针。

为了使用方便,C语言规定:
可以用一个函数的函数名,来代表该函数所占内存区的首地址

正如数组名属于指针常量一样,函数名也属于指针常量

此外在C语言中还可以定义指向函数的指针变量

定义指向函数的指针变量
一般形式:
<数据类型>(*变量名)(形参类型)
例如:
int (*p)(int,int);
p是指针变量,指向函数的指针变量,所指向的函数的返回值为int,并且具有两个int型的形参

利用指向函数的指针变量调用函数方式比较繁琐,但他的优势在于 :
它可以用作其他函数的参数

int (p)(int int)
//p先跟
结合,说明是指针变量

int *p(int,int);
//p先跟()结合,说明是指针型函数,返回值是指向int的指针类型


代码示例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int add(int m, int n)
{
	return m + n;
}

int sub(int m, int n)
{
	return m - n;
}

int mul(int m, int n)
{
	return m * n;
}

int div(int m, int n)
{
	return m / n;
}

//函数指针作为参数,可用作回调函数
int fun(int m, int n, int (*p)(int, int))
{
	return p(m, n);
}

//int main()
//{
//	int (*p)(int m, int n);  //定义一个函数指针
//	p = add;                 //让p 指向 add 函数
//	int m = 10;
//	int n = 5;
//	printf("m+n = %d\n", p(m, n));  //直接调用p(m,n)
//	/*
//	直接调用 p(m, n)
//	当你使用 p(m, n) 时,编译器会自动将 p 解释为一个函数指针,
//	并调用它指向的函数。这是因为C语言标准允许函数指针像普通函数一样直接调用。
//	*/
//	printf("m+n = %d\n", (*p)(m, n));  //间接引用,解引用调用p(m,n)
//	/*
//	当你使用 (*p)(m, n) 时,你显式地对函数指针 p 进行解引用操作,
//	得到它指向的函数,然后再调用这个函数。这也是C语言标准允许的调用方式。
//	*/
//	p = sub;
//	printf("m-n = %d\n", p(m, n));
//	printf("m-n = %d\n", (*p)(m, n));
//
//	return 0;
//}

/*
函数指针数组
*/
//int main()
//{
//	int m = 10, n = 20;
//	int (*p[2])(int, int);
//	
//	p[0] = add; //函数入口
//	printf("%d\n", (*p[0])(m, n));
//
//	p[1] = sub;
//	printf("%d\n", (*p[1])(m, n));
//}

/*函数指针做参数*/
//int main()
//{
//	int m, n;
//	int (*p)(int, int);  //定义函数指针
//
//	scanf("%d %d", &m, &n);
//
//	p = add;
//	printf("+ %d\n", p(m, n));
//
//	p = sub;
//	printf("- %d\n", p(m, n));
//
//	p = mul;
//	printf("* %d\n", p(m, n));
//
//	p = div;
//	printf("/ %d\n", p(m, n));
//
//	//函数指针做参数
//	printf("fun:%d\n", fun(m, n, add));
//
//	return 0;
//}

int main()
{
	int m, n, i;
	int (*p[4])(int, int);

	scanf("%d%d", &m, &n);

	p[0] = add;
	p[1] = sub;
	p[2] = mul;
	p[3] = div;

	for (i = 0; i < 4; i++)
	{
		printf("%d\n", p[i](m, n));
	}
}

http://www.kler.cn/a/535254.html

相关文章:

  • RFID隧道机:提升生产流水线效率与精准度
  • [paddle] 矩阵的分解
  • 在Debian 12上安装VNC服务器
  • Linux 源码编译安装httpd 2.4,提供系统服务管理脚本并测试
  • stm32点灯 GPIO的输出模式
  • 【Origin笔记-2】降水量变化趋势单位理解
  • wait/notify/join/设计模式
  • 无人机动力套(电机、电调)技术详解
  • mysql8的并行复制介绍
  • Git 远程仓库的操作与协作
  • 离散浣熊优化算法(DCOA)求解大规模旅行商问题(Large-Scale Traveling Salesman Problem,LTSP),MATLAB代码
  • 基于Typescript,使用Vite构建融合Vue.js的Babylon.js开发环境
  • 2025年Android NDK超全版本下载地址
  • Pycharm 2024版本出现 We could not validate your license怎么办?解决方法一步到位!
  • 疯狂SQL转换系列- SQL for Milvs2.4
  • GD32F4xx系列微控制器中,定时器可以配置为霍尔传感器模式,用于处理霍尔传感器的输出信号
  • GNN多任务预测模型实现(二):将EXCEL数据转换为图数据
  • 数据实时推送至前端的主流方法总结
  • 为何实现大语言模型的高效推理以及充分释放 AI 芯片的计算能力对于企业级落地应用来说,被认为具备显著的研究价值与重要意义?
  • 面向对象程序设计-实验1
  • 快速单机部署ollama v0.5.7 +openwebui(免去网络环境干扰)
  • 【后端开发】系统设计101——Devops,Git与CICD,云服务与云原生,Linux,安全性,案例研究(30张图详解)
  • 下标为3的倍数
  • 解锁C#数据校验:从基础到实战的进阶之路
  • 日志模块自定义@SkipLogAspect注解跳过切面
  • 三格电子-单串口服务器说明