C语言之指针进阶(3),函数指针


目录

前言:

一、函数指针变量的概念

二、函数指针变量的创建

三、函数指针变量的使用

四、两段特殊代码的理解

五、typedef

六、函数指针数组

总结:


前言:

        本文主要讲述C语言指针中的函数指针,包括函数指针变量的概念、创建及使用。两段特殊代码的理解,typedef关键字的使用,以及函数指针数组的使用,最后还有一个代码案例--计算器的实现。希望对大家有所帮助。


一、函数指针变量的概念

函数指针变量,是用于存储函数地址的指针变量

那么,函数有地址吗?函数名与地址有关吗?

简单测试一下:

我们发现:函数名和取地址函数名得到的地址是一样的

函数名本身可以被视为一个地址,指向函数代码的起始位置,这与&函数名一样,使用起来并无区别


二、函数指针变量的创建

既然函数名和&函数名得到了函数的地址,我们要存储这种地址,就需要创建函数指针变量

定义语法:函数返回类型(*变量名)(形参类型,形参类型)

如:

调试监视其值:

观察类型我们可以得知,函数指针变量的类型就是:去掉变量名,剩下的就是函数指针变量的类型

函数指针类型解析:

int  (*pf4) (int x, int y)

  • int:pf4指向的函数类型
  • pf4:函数指针变量名,*表明其为指针变量
  • (int x, int y):pf4指向函数的参数类型和个数的交代


三、函数指针变量的使用

通过函数指针调用指针指向的函数

使用方法1:

该方法就是通过解引用指针,找到函数地址,然后传入参数,接收返回值

使用方法2:

直接写函数指针变量的变量名,然后传入参数,这与直接写函数名传入参数是一样的,因为该指针变量值就等于函数名的地址

其实方法1中,*pf前面的*号本身无实际作用

我们无论写多少*号,结果是一样的,编译器没有对这个符号进行相关操作,故相当于摆设了,不过为了提高可读性,一般是写一个*号

注意:*pf必须用括号括起来,因为左边优先级高于*号,不加括号会被编译器认为是解引用函数的返回值,而这是一个非法访问


四、两段特殊代码的理解

1.( *(  void (*)()  ) 0 ) ()

请问这段代码是什么意思?

这其实是一次函数调用的代码,调用0地址处的函数

那么如何分析这段代码呢,我们画图来理解:

注意:该代码出自《C陷阱与缺陷》一书,情景是一位程序员需要写一个独立运行于某种微处理器上的C程序,当计算机启动时,硬件将调用0地址处的子例程(函数)。于是设计出了这段代码


2.void ( *signal( int , void(*)(int) ) )(int);

请问这段代码是什么意思?

答案是:这是一个函数声明。我们画图分析

以上难以理解的可能就是第3步,按照以往的理解,理论上函数的返回类型不应该写在函数名前面吗,也就是下面这样

我们发现把 void(*)(int) 的返回类型写在函数名前面,编译器报错了

这其实是语法规定的,函数指针作为返回类型,函数名需写在类型的里面,也就是*号的旁边,上面那种才是正确的写法


五、typedef

我们发现上面那段代码是不是较难看懂,如果能让其与一般函数写法一样,也就是函数返回类型写在前面就好了,这里就有一个方法,使用typedef重命名

typedef:对类型名进行重命名

例1:重命名unsigned int

例2:重命名数组指针

注意:数组指针重命名,重命名的名字要放在括号里边

现在,就让我们把void ( *signal( int , void(*)(int) ) )(int)进行重命名:

注意:与数组指针一样,我们重命名的名字要放在类型里面,之后我们不管是以返回类型写在函数名前面,还是以函数参数类型写在参数里都可以,这样看代码是不是明朗了许多


六、函数指针数组

函数指针数组:存储函数指针的数组,数组的元素都是一个个类型相同的函数指针

定义语法:见下面第二张图

例如:

如上,两个相同类型的函数指针变量我们可以定义,可是当相同类型的函数多起来后,如果我们需要储存这些函数的地址,就需要数组来接收才方便了。

如:

注意:定义函数指针数组,数组放在数组类型里边

调用数组元素时,就正常使用下标+传入参数即可

如果觉得以上内容简单,我们可以实现一个简单案例

简单计算器的实现:

#include <stdio.h>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 menu()
{printf("***************************************\n");printf("**********  1.Add     2.Sub  **********\n");printf("**********  3.Mul     4.Div  **********\n");printf("**********      0.exit       **********\n");printf("***************************************\n");
}int main()
{int(*pf_arr[5])(int, int) = { 0,Add,Sub,Mul,Div };int input = 0;do{menu();printf("请选择:\n");scanf("%d", &input);if (input >= 1 && input <= 4){int a = 0;int b = 0;printf("请输入两个整数:\n");scanf("%d %d", &a, &b);printf("%d\n", pf_arr[input](a, b));}else if (input == 0){printf("程序退出\n");break;}else{printf("选择错误,请重新选择:\n");}} while (input);return 0;
}


总结:

        以上就是本文的全部内容了,希望对大家有所帮助,哪里有问题欢迎提出,感谢大家的支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/15534.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【面试干货】事务的并发问题(脏读、不可重复读、幻读)与解决策略

【面试干货】事务的并发问题&#xff08;脏读、不可重复读、幻读&#xff09;与解决策略 一、脏读&#xff08;Dirty Read&#xff09;二、不可重复读&#xff08;Non-repeatable Read&#xff09;三、幻读&#xff08;Phantom Read&#xff09;四、总结 &#x1f496;The Begi…

Stable Diffusion——U-ViT用于扩散建模的 ViT 主干网

1.概述 扩散模型是最近出现的强大的深度生成模型&#xff0c;可用于生成高质量图像。扩散模型发展迅速&#xff0c;可应用于文本到图像生成、图像到图像生成、视频生成、语音合成和 3D 合成。 除了算法的改进&#xff0c;骨干网的改进在扩散建模中也发挥着重要作用。一个典型…

汽车R155法规中,汽车获取到的VTA证书,E后面的数字表示什么意思?

标签&#xff1a; 汽车R155法规中&#xff0c;汽车获取到的VTA证书&#xff0c;E后面的数字表示什么意思&#xff1f;&#xff1b; 汽车&#xff1b;VTA认证; 有些厂商汽车拿到的VTA证书上面写着E9&#xff0c; 有些厂商汽车拿到的VTA证书上面写着E5&#xff0c;E9与E5有什么差…

嵌入式之音频基础知识

声音特性 1、响度&#xff1a;人主观上感觉声音的大小&#xff08;俗称音量&#xff09;&#xff0c;由“振幅”和人离声源的距离决定&#xff0c;振幅越大响度越大&#xff0c;人和声源的距离越小&#xff0c;响度越大&#xff1b; 2、音调&#xff1a;声音的高低&#xff0…

多商户消费券系统源码(ThinkPHP+FastAdmin+微信公众号)

打造智能促销新体验 一、引言&#xff1a;消费券系统的时代意义 在当今这个数字化高速发展的时代&#xff0c;电子商务和移动支付已经成为人们日常生活的重要组成部分。随着市场竞争的加剧&#xff0c;多商户消费券系统作为一种创新的促销手段&#xff0c;正逐渐受到商家和消…

从零训练yolov8

1.收集数据 2.数据标注 pip install labelimg3.划分数据集 0.2的验证机0.8的训练集 import os from shutil import copyfile from sys import exit import randomsource r"D:\Data\imgs\screenc" \\ target_train r"D:\Data\imgs\datasets\mydata\images\t…

aws msk加密方式和问控制连接方式

msk加密方式 msk提供了两种加密方式 静态加密传输中加密 创建集群时可以指定加密方式&#xff0c;参数如下 aws kafka create-cluster --cluster-name "ExampleClusterName" --broker-node-group-info file://brokernodegroupinfo.json --encryption-info file:/…

Android四大组件 Broadcast广播机制

一 概述 广播 (Broadcast) 机制用于进程或线程间通信&#xff0c;广播分为广播发送和广播接收两个过程&#xff0c;其中广播接收者 BroadcastReceiver 是 Android 四大组件之一。BroadcastReceiver 分为两类&#xff1a; 静态广播接收者&#xff1a;通过 AndroidManifest.xm…

flutter 实现旋转星球

先看效果 planet_widget.dart import dart:math; import package:flutter/material.dart; import package:vector_math/vector_math_64.dart show Vector3; import package:flutter/gestures.dart; import package:flutter/physics.dart;class PlanetWidget extends StatefulW…

echarts-树图、关系图、桑基图、日历图

树图 树图主要用来表达关系结构。 树图的端点也收symbol的调节 树图的特有属性&#xff1a; 树图的方向&#xff1a; layout、orient子节点收起展开&#xff1a;initialTreeDepth、expandAndCollapse叶子节点设置&#xff1a; leaves操作设置&#xff1a;roam线条&#xff1a…

2、xss-labs之level2

1、打开页面 2、传入xss代码 payload&#xff1a;<script>alert(xss)</script>&#xff0c;发现返回<script>alert(xss)</script> 3、分析原因 打开f12&#xff0c;没什么发现 看后端源码&#xff0c;在这form表单通过get获取keyword的值赋给$str&am…

【Vue】input框自动聚焦且输入验证码后跳至下一位

场景&#xff1a;PC端 样式&#xff1a; <div class"verification-code-input"><input v-model"code[index]" v-for"(_, index) in 5" :key"index" type"text" maxlength"1" input"handleInput(i…

渲染管线——应用阶段

知识必备——CPU和GPU 应用阶段都做了什么 应用阶段为渲染准备了什么 1.把不可见的数据剔除 2.准备好模型相关数据&#xff08;顶点、法线、切线、贴图、着色器等等&#xff09; 3.将数据加载到显存中 4.设置渲染状态&#xff08;设置网格需要使用哪个着色器、材质、光源属性等…

【机器学习】机器学习与大型预训练模型的前沿探索:跨模态理解与生成的新纪元

&#x1f512;文章目录&#xff1a; &#x1f4a5;1.引言 ☔2.跨模态理解与生成技术概述 &#x1f6b2;3.大型预训练模型在跨模态理解与生成中的应用 &#x1f6f4;4.前沿探索与挑战并存 &#x1f44a;5.未来趋势与展望 &#x1f4a5;1.引言 近年来&#xff0c;机器学习领…

著名书法家王杰宝做客央视频《笔墨写人生》艺坛人物经典访谈节目

印象网北京讯&#xff08;张春兄、冯爱云&#xff09;展示艺术风采&#xff0c;构建时代精神。5月25日&#xff0c;著名书法家、羲之文化传承人王杰宝&#xff0c;做客央视频《笔墨写人生》艺坛人物经典访谈节目&#xff0c;与中央电视台纪录频道主持人姚文倩一起&#xff0c;分…

SpringBoot 集成 ChatGPT(附实战源码)

建项目 项目结构 application.properties openai.chatgtp.modelgpt-3.5-turbo openai.chatgtp.api.keyREPLACE_WITH_YOUR_API_KEY openai.chatgtp.api.urlhttps://api.openai.com/v1/chat/completionsopenai.chatgtp.max-completions1 openai.chatgtp.temperature0 openai.cha…

全局平均池化笔记

全局平均池化&#xff08;Global Average Pooling, GAP&#xff09;是一种用于卷积神经网络&#xff08;CNN&#xff09;中的池化操作&#xff0c;其主要作用和优点包括&#xff1a; 减少参数数量&#xff1a;全局平均池化层将每个特征图通过取其所有元素的平均值&#xff0c;压…

ubuntu安装yum方法【最新可用】

一、安装命令 在根目录&#xff08;root&#xff09;下执行 sudo apt-get install build-essential sudo apt-get install yum二、出错处理 1、E: Package yum has no installation candidate 解决&#xff1a;更换镜像源&#xff0c;找到自己的系统版本用vim进行更换&#xff…

GmSSL3.X编译iOS和Android动态库

一、环境准备 我用的Mac电脑编译&#xff0c;Xcode版本15.2&#xff0c;安卓的NDK版本是android-ndk-r21e。 1.1、下载国密源码 下载最新的国密SDK源码到本地。 1.2、安装Xcode 前往Mac系统的AppStore下载安装最新Xcode。 1.3、安卓NDK下载 下载NDK到本地&#xff0c;选…

Protobuf - 语法、字段使用规则、注意事项

目录 前言 一、Protobuf 基本语法 1.1、Protoc 版本 1.2、文件格式配置 1.3、消息字段规则 1.3.1、字段数据类型 1.3.2、字段修饰规则 1.3.3、消息类型定义 1.3.4、enum 类型 1.3.5、Any 类型 1.3.6、oneof 类型 1.3.7、map 类型 1.3.8、默认值 1.3.9、更新消息…