C语言指针进阶(2)
大家好,我们今天继续来分享指针进阶的内容。

目录
5.函数指针
6.函数指针数组
7. 指向函数指针数组的指针
8. 回调函数
5.函数指针
顾名思义函数指针里面存的就是函数的地址了。
那我们通过一段代码来理解函数指针:
#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
//&函数名 - 拿到的就是函数的地址
//函数名 - 也是函数的地址
int main()
{printf("%p\n", &Add);printf("%p\n", Add);//int (* pf)(int, int) = &Add;//pf就是一个函数指针变量的int (* pf)(int, int) = Add;int ret = pf(3, 5);int ret2 = Add(3, 5);printf("%d\n", ret);printf("%d\n", ret2);//int arr[10];//int (*pa)[10] = &arr;//pa就是数组指针变量return 0;
}
我们看到函数指针*pf,因为我们定义的函数传参传的是整形的变量,所以我们传递的参数类型也是int型的,又因为我们定义的函数也是int类型的,所以我们的指针 *p返回的类型也是int型,那么我们对于函数Add取地址和对函数名取地址和发现两个地址相同,那就说明&函数名和函数名都是函数的地址,所以我们最后用函数指针变量还是调用函数都可以打印出ret和ret2,且二者值相同。

相信大家对于函数指针有了深刻的理解。
6.函数指针数组
函数指针数组是存放函数指针的数组。
话不多说,直接看代码—>:
int Add(int x, int y)
{return x + y;
}int Sub(int x, int y)
{return x - y;
}int main()
{int (*pf1)(int, int) = &Add;int (*pf2)(int, int) = ⋐//数组中存放类型相同的多个元素int (* pfArr[4])(int, int) = {&Add, &Sub};//pfArr 是函数指针数组 - 存放函数指针的数组return 0;
}
在这里我们定义了两个函数,分别对他们取地址,并存入到一个数组中,这个数组我们就叫做函数指针数组,我们将函数指针和函数指针数组进行比较发现我们的函数指针数组比函数指针多了[ ]且里面定义了这个数组的大小,所以我们要设置一个函数指针数组的时候就可以多想想函数指针就可以很快的写出函数指针数组了。
- 回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个
函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数
的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进
行响应。
在这里我们将会用很简单的例子来让大家更加的理解所谓的回调函数。
void menu()
{printf("****************************\n");printf("*** 1. add 2. sub ***\n");printf("*** 3. mul 4. div ***\n");printf("*** 0. exit ***\n");printf("****************************\n");
}
//+ - * / && || & | >> <<int Add(int x, int y)
{return x + y;
}int Sub(int x, int y)
{return x - y;
}int Mul(int x, int y)
{return x * y;
}int Div(int x, int y)
{return x / y;
}int main()
{int input = 0;int x = 0;int y = 0;int ret = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = Add(x, y);printf("ret = %d\n", ret);break;case 2:printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = Sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = Mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = Div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出计算器\n");break;default:printf("选择错误, 重新选择\n");break;}} while (input);return 0;
}
这里我们通过一个小程序来向大家讲述,我们这里定义了一个菜单来进行加减乘除运算,便于我们进行加减乘除运算。
1.首先我们打开程序

2.输入我们想要进行运算所代表的数字,我们代码块中通过swith来对这个加以控制,1代表加法运算,2代表减法运算,3代表乘法运算,4代表除法运算,0则是退出程序。我们就以加法运算为例输入1。

3.接着我们就得输入两个操作数,输入后我们的case1分支语句就会调用Add函数将这两个操作数传给函数,函数内通过运算返回两个数之后,在打印出来。我们以输入1和2为例。

4.我们结束一个运算过程之后紧接着就会让你进行下一个你想要的运算,除非输入0,否则这个程序永远都不会结束。

我们看到输入1就退出程序了,就结束程序了。那么问题来了如果我们要进行很多操作数的运算是不是就得一直进行程序运算呢,那么这样的过程是不是就会显得太冗杂了呢?为了提高操作的效率,那么就到了我们要讲的主体回调函数了。
我们对代码进行修改
void menu()
{printf("****************************\n");printf("*** 1. add 2. sub ***\n");printf("*** 3. mul 4. div ***\n");printf("*** 0. exit ***\n");printf("****************************\n");
}
//+ - * / && || & | >> <<int Add(int x, int y)
{return x + y;
}int Sub(int x, int y)
{return x - y;
}int Mul(int x, int y)
{return x * y;
}int Div(int x, int y)
{return x / y;
}void calc(int (*pf)(int,int))
{int x = 0;int y = 0;int ret = 0;printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}int main()
{int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:calc(Add);break;case 2:calc(Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;case 0:printf("退出计算器\n");break;default:printf("选择错误, 重新选择\n");break;}} while (input);return 0;
我们这里用了一个函数calc分装起来,通过将函数加减乘除的地址传给函数calc,在calc函数中输入的操作数将会传到我们要进行操作的函数中,通过操作后将结果返回到calc函数中在进行打印。所以我们这里的函数calc相当于一个中转站。所以我们想要进行什么运算就只要输入相应函数对应的数字就可以了。

我们在这里通过图片就可以很清楚的看到整个程序进行的过程。
通过今天的分享相信大家应该对指针进阶内容有了更加深刻的认识,今天的分享就到这里,谢谢大家。
相关文章:
C语言指针进阶(2)
大家好,我们今天继续来分享指针进阶的内容。 目录 5.函数指针 6.函数指针数组 7. 指向函数指针数组的指针 8. 回调函数 5.函数指针 顾名思义函数指针里面存的就是函数的地址了。 那我们通过一段代码来理解函数指针: #include<stdio.h> int Add…...
51 单片机 led 灯光操作
led流水灯 #include <REGX52.H> #include "INTRINS.H"void Delay(unsigned int xms) {unsigned char i, j;while(xms--){_nop_();i 2;j 199;do{while (--j);} while (--i);}}void main(){while(1){P20xFE;Delay(500);P20xFD;Delay(500);P20xFB;Delay(500)…...
VSCODE 使用技巧
vscode批量去掉代码中空行的方法 1、在vscode中使用ctrl f组合快捷键打开替换窗口. 2、输入下面的正则表达式 ^\s*(?\r?$)\n https://mp.weixin.qq.com/s/ZKV2sZWszxBLNTNLEWhsng 你的代码够安全吗?推荐5个VS Code代码安全插件 VSCode:人生苦短&…...
数据库安全(Mysql,Hadoop,Redis)
MySQL Mysql 身份认证绕过漏洞(CVE-2012-2122) 当连接MariaDB/MySQL时,输入的密码会与期望的正确密码比较,由于不正确的处理,会导致即便是memcmp()返回一个非零值,也会使MySQL认为两个密码是相同的。也就…...
C【动态内存管理】
1. 为什么存在动态内存分配 int val 20;//在栈空间上开辟四个字节 char arr[10] {0};//在栈空间上开辟10个字节的连续空间 2. 动态内存函数的介绍 2.1 malloc:stdlib.h void* malloc (size_t size); int* p (int*)malloc(40); #include <stdlib.h> #incl…...
Javase | 集合-上
目录: 一、集合:1.集合的概述2.集合的分类 二、“单个方式”存储元素:1.Collection1.1 Collection的概述1.2 Collection接口中常用的方法Iterator<T> iterator( ) 1.3 Collection下的子接口 2.Iterable:2.1 Iterable的概述2…...
Multitor:一款带有负载均衡功能的多Tor实例创建工具
关于Multitor Multitor是一款带有负载均衡功能的多Tor实例创建工具,Multitor的主要目的是以最快的速度完成大量Tor进程的初始化,并将大量实例应用到我们日常使用的程序中,例如Web浏览器和聊天工具等等。除此之外,在该工具的帮助下…...
AIGC专栏6——通过阿里云与AutoDL快速拉起Stable Diffusion和EasyPhoto
AIGC专栏6——通过阿里云与AutoDL快速拉起Stable Diffusion和EasyPhoto 学习前言Aliyun DSW快速拉起(新用户有三个月免费时间)1、拉起DSW2、运行Notebook3、一些小bug AutoDL快速拉起1、拉起AutoDL2、运行Notebook 学习前言 快速拉起AIGC服务 对 用户体…...
Mysql的逻辑架构、存储引擎
1. 逻辑架构剖析 1.1 服务器处理客户端请求 首先MySQL是典型的C/S架构,即Clinet/Server 架构,服务端程序使用的mysqld。 不论客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果是:客户端进程向服务器进程发送一段文…...
[ES6]模块
[ES6]模块 特点export 与 import基本用法导入导出基本方式导入导出等价方式html 导入 别名导出默认导出基本用法默认导出对象 复合使用import 命令的特点只读属性单例模式静态执行特性 在 ES6 前, 实现模块化使用的是 RequireJS 或者 seaJS(分别是基于 AMD 规范的模…...
物联网终端算法
物联网终端算法是指在物联网终端设备上运行的各种算法,包括数据采集、数据预处理、数据传输、数据存储、数据处理、数据分析等算法。以下是物联网终端算法的一些具体应用: 数据采集算法:用于采集各种传感器数据,包括温度、湿度、气…...
【面试刷题】——TCP三次握手,以及为什么要三次握手
TCP(传输控制协议)的三次握手是建立TCP连接的过程,它确保了通信双方的正常启动和参数协商。三次握手的过程如下: 客户端发送请求: 客户端首先向服务器发送一个特殊的TCP报文,称为SYN(同步&…...
算法系列-力扣206-单链表反转
题目说明 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 方法一:头插法反转链表 思路: 声明p指针指向原头节点,并将头节点置空;p指针循环原链表将元素用头节点插入法逐个插入head中&…...
网络基础-应用层协议-HTTP/HTTPS
HTTP/HTTPS HTTP基本概念协议格式请求报文请求方法请求资源地址协议版本 应答报文 常见Header常见状态码与状态描述Cookie&Sessionhttp协议特点 HTTPS基本概念对称加密与非对称加密数据摘要&数据指纹HTTPS工作过程探究只采用对称加密只采用非对称加密双方都采用非对称加…...
problen(5)ubuntu版本问题
浅浅记录一下这段时间的血和泪吧,大概耗时快一个月了吧,终于解决了...... 因为需要开启pwn之旅,需要在Ubuntu上安装一些东西,就是下面的一条命令: sudo pip3 install pwntools -i Simple Index(显示不太好了…...
写一篇nginx配置指南
nginx.conf配置 找到Nginx的安装目录下的nginx.conf文件,该文件负责Nginx的基础功能配置。 配置文件概述 Nginx的主配置文件(conf/nginx.conf)按以下结构组织: 配置块功能描述全局块与Nginx运行相关的全局设置events块与网络连接有关的设置http块代理…...
rhel8防火墙firewalld操作
1.查看默认区域 [rootlocalhost r]# firewall-cmd --get-default-zone public2.查看网卡关联的区域 [rootlocalhost r]# firewall-cmd --get-zone-of-interfaceifcfg-ens160 external 3.设置网卡的默认区域修改为work [rootlocalhost r]# firewall-cmd --zonework --change…...
OpenCV项目实战(2)— 如何用OpenCV实现弹球动画
前言:Hello大家好,我是小哥谈。OpenCV能够在画布上绘制静态的图形,例如,线段、矩形、正方形、圆形、多边形、文字等。那么,能不能让这些静态的图形移动起来?如果能,又该如何编写代码呢ÿ…...
golang iris框架 + linux后端运行
go mod init myappgo get github.com/kataras/iris/v12latestpackage mainimport "github.com/kataras/iris/v12"func main(){app : iris.New()app.Listen(":port") }打包应用 go build main.go开启服务 #nohup ./程序名称 nohup ./main关闭后台 #ps -e…...
linux shell操作- 02 常用命令及案例
文章目录 常用命令 续 常用命令 续 定时任务 通过文本编辑cron任务,实现定时操作 分 小时 天 月 星期 绝对路径sh or cmd* 表示每个xxx,如每个小时每小时的第三分钟执行cmd-> 03 * * * * /home/lauf/scraw.sh每天的第5、8个小时执行-> 00 5,8 * *…...
如何用deberta-v3-base-zeroshot-v2.0构建企业级NLP应用?完整教程来了
如何用deberta-v3-base-zeroshot-v2.0构建企业级NLP应用?完整教程来了 【免费下载链接】deberta-v3-base-zeroshot-v2.0 项目地址: https://ai.gitcode.com/hf_mirrors/NingBo_Ascend/deberta-v3-base-zeroshot-v2.0 deberta-v3-base-zeroshot-v2.0是一款基…...
具身智能:面向新兴交叉学科建设的思考与建议 2026
这份由 CCF YOCSEF 长三角五地学术委员会 2026 年 5 月发布的白皮书,聚焦具身智能作为新兴交叉学科的建设,明确其并非 AI 与机器人学的简单拼接,而是围绕物理交互中的智能行为形成的新问题域,提出 “三大基本问题 一个应用需求”…...
安卓用户如何免费获取大模型API密钥并开始调用
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 安卓用户如何免费获取大模型API密钥并开始调用 对于安卓开发者或移动端技术爱好者而言,直接体验和调用多种大模型的能力…...
【Sora 2 HDR生成黄金公式】:曝光补偿系数×动态范围压缩阈值×时域一致性权重=可商用HDR帧率(附Python验证脚本)
更多请点击: https://codechina.net 第一章:Sora 2 HDR视频生成黄金公式的提出与商业意义 Sora 2 的HDR视频生成能力不再依赖传统多曝光融合或后期调色管线,而是通过一个端到端可微分的物理感知渲染公式实现原生高动态范围建模。该公式被业界…...
别再用BLEU和ROUGE了!2024最前沿的DeepSeek评估范式:基于认知对齐度(CA-Score)的三维量化体系
更多请点击: https://intelliparadigm.com 第一章:别再用BLEU和ROUGE了!2024最前沿的DeepSeek评估范式:基于认知对齐度(CA-Score)的三维量化体系 传统自动评估指标如BLEU、ROUGE长期受限于n-gram表面匹配&…...
揭秘CuCl超低热导率:四声子散射与温度重正化的关键作用
1. 项目概述:为何要深挖CuCl的热导率?在材料科学和凝聚态物理的交叉领域,热输运性质的研究从来都不是一个孤立的课题。它直接关系到热电材料的转换效率、电子器件的散热能力,以及热障涂层的服役寿命。传统上,我们倾向于…...
别再只搭环境了!用LangChain+ChromaDB在Mac上快速构建你的第一个私有知识库问答机器人
从零构建Mac上的智能知识管家:LangChainChromaDB实战指南 你是否厌倦了在成堆的文档中手动搜索信息?想象一下,只需简单提问,就能从你的笔记、报告或任何文本资料中获取精准答案。本文将带你用Mac电脑打造一个真正的私有知识库助手…...
Keil µVision许可证失效问题解析与解决方案
1. 问题现象与背景解析最近遇到一个挺有意思的案例:一位工程师在安装了Windows Media Center后,突然发现Keil Vision IDE变成了评估版模式。这种情况其实在嵌入式开发领域并不罕见,但很多开发者第一次遇到时都会感到困惑。本质上,…...
HFSS的Solution type及其激励端口设置规则
本文围绕Ansys HFSS 电磁仿真展开,依次探讨辐射边界特性、软件求解类型、PCB 板载天线求解选型、两类端口原理差异、端口信号地判定与集总端口参考面设置、求解与端口适配规则六大板块内容,完整梳理如下:一、HFSS 辐射边界条件相关讨论基本定…...
RTX51多任务环境下printf安全调用方案解析
1. RTX51多任务环境下printf的安全调用方案在RTX51实时操作系统中,多个任务同时调用标准库函数printf时会出现"多重调用警告"(Warning 15: MULTIPLE CALL TO SEGMENT)。这个看似简单的调试输出问题,实际上涉及RTOS任务调度、函数重入、内存管理…...
