指针的介绍3后

1.函数指针变量

1.1函数的地址

void test(int (*arr)[2])
{printf("zl_dfq\n");
}
int main()
{printf("%p\n", test);printf("%p\n", &test);return 0;
}

由上面的程序运行可知:

函数名就是函数的地址

&函数名也可以拿到函数的地址

1.2函数指针变量

1.2.1函数指针变量的引入

学习完整型指针变量,字符指针变量,数组指针变量之后,我们不难推出

函数指针变量就是一个存放函数地址的变量

void test(int a, int b)
{printf("%d\n", a);printf("%d\n", b);
}
int main()
{void(*p)() = test;return 0;
}

指针 p 就拿到了函数 test 的地址

 

1.2.2函数指针变量的书写

 void(*p)(int a, int b) 去掉标识符 p 就是该指针的类型

即,p 指向了一个 void (*) (int a, int b) 型的函数

记忆方法:

(1)

 void(*p)(int a, int b) 如果去掉第一个括号,变为

 void* p(int a, int b)

那么,这将变成一个函数的声明

函数名为 p ,形参为(int a, int b), 返回值为 void*

(2)

注意:

函数指针变量中,函数的

形参按原函数的顺序

可以只写类型,不写形参名

即 void(*p)(int a, int b) ==  void(*p)(int , int )

1.2.3函数指针变量的使用

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

void test(int a, int b)
{printf("%d\n", a);printf("%d\n", b);
}
int main()
{void(*p)(int a, int b) = test;(*p)(3, 5);return 0;
}

(*p)(3, 5);

p拿到了函数test的地址

*p就拿到了函数, *p == test

此时传参即可

但注意*p要用()括起来,不然p会先于第二个()结合

 

由上面的程序运行发现:

(1)可以通过函数指针直接调用函数

(2)多次解引用指针, 没啥影响

实际上,

(1)编译器是直接通过地址找到函数,并调用的

此时并没有进行, *解引用操作

总结:

(1)

(*p)(3, 5)有解引用的书写 便于理解

p(3, 5)无解引用的书写 简化符号

(2)对于函数名来说,前面的&和*都会被忽略

 1.3 typedef关键字

定义:typedef 关键字被用于为一个已存在的数据类型创建一个新的名称(别名)

用法:

typedef existing_type new_type_name;

注意:

对函数指针和数组指针创建别名时,标识符要放在(*)中

typedef void(*a)(int) ;//right
typedef void(*)(int) a;//err
typedef int(*a)[10] ;//right
typedef int(*)[10] a;//err

1.4两段有趣的代码

1.4.1第一段

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

解析:

(1)粉方框框起来的意思是

这是一个函数指针类型

(2)黑方框框起来的意思是

这将进行显示类型转换

(3)黄方框框起来的意思是

将 0 转换为一个函数指针

(4)红方框框起来的意思是

解引用函数指针,并调用该函数

 1.4.2第二段

 函数返回值是一个函数指针的时候,

函数的书写形式:

 void (* signal(int) )(int); //rightvoid (*  )(int) signal(int);//err

所以请看题:

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

解析:

(1)黑方框框起来的意思是

这是一个函数

(2)粉方框框起来的意思是

函数的返回值是一个函数指针

实在是过于纷乱,使用typedef简化名称

typedef void(*fac)(int) ;
 void (*signal(int , void(*)(int)))(int);
fac signal(int , fac); 

代码就简单易懂啦!

2.函数指针数组与转移表

2.1相关含义

函数指针数组就是存放函数指针的数组

 void(*)() p[10]; //err
void(*p[10])();   //right

第二行代码才是正确的函数指针数组的书写形式

标识符[元素个数] 写入 函数指针的(*)中

函数指针数组的用途:转移表

转移表(Jump Table),也叫跳转表,是一种用于实现多分支选择结构的数据结构或技术

转移表通常用于替代复杂的if-else或switch语句

2.2举例之简易计算器的实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>int Add(int a, int b)
{return a + b;
}
int Sub(int a, int b)
{return a - b;
}
int Mul(int a, int b)
{return a * b;
}
int Div(int a, int b)
{return a / b;
}
void menu()
{printf("****************************\n");printf("****************************\n");printf("****   1.Add   2.Sub   *****\n");printf("****   3.Mul   4.Div   *****\n");printf("****   0.OUT           *****\n");printf("****************************\n");printf("****************************\n");
}
int main()
{int input;do{menu();printf("请选择:");scanf("%d", &input);int x = 0;int y = 0;switch (input){case 1:printf("请输入两个操作数:");scanf("%d %d", &x, &y);int ret1 = Add(x, y);printf("%d\n", ret1);break;case 2:printf("请输入两个操作数:");scanf("%d %d", &x, &y);int ret2 = Sub(x, y);printf("%d\n", ret2);break;case 3:printf("请输入两个操作数:");scanf("%d %d", &x, &y);int ret3 = Mul(x, y);printf("%d\n", ret3);break;case 4:printf("请输入两个操作数:");scanf("%d %d", &x, &y);int ret4 = Div(x, y);printf("%d\n", ret4);break;case 0:printf("已退出计算器\n");break;default:printf("选择有误,请重新选择\n");}} while (input);return 0;
}

不难发现 switch 语句中 有大量的重复语句,

并且如果加上 & ^ ~ 等计算,会使代码更加冗余

此时想到转移表

只需要修改main 函数部分

int main()
{int (*Funcs[5])(int, int) = { 0, Add, Sub, Mul, Div };int input;do{menu();printf("请选择:");scanf("%d", &input);if (input >= 1 && input <= 4){int x = 0;int y = 0;printf("请输入两个操作数:");scanf("%d %d", &x, &y);int ret = Funcs[input](x, y);printf("%d\n", ret);}else if (input == 0){printf("已退出计算器\n");}else{printf("选择有误,请重新选择\n");}} while (input);return 0;
}

(1)使用函数指针数组中存放每个函数的地址

(2)函数指针数组中,使用 0 占位

使数组下标对应菜单选项

这样以后,代码更加简洁,并且增添都很方便

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

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

相关文章

春晚舞台上的人形机器人:科技与文化的奇妙融合

文章目录 人形机器人Unitree H1的“硬核”实力传统文化与现代科技的创新融合网友热议与文化共鸣未来展望&#xff1a;科技与文化的更多可能结语 2025 年央视春晚的舞台&#xff0c;无疑是全球华人目光聚焦的焦点。就在这个盛大的舞台上&#xff0c;一场名为《秧BOT》的创意融合…

连接 OpenAI 模型:基础操作

在这一部分中&#xff0c;我们将介绍如何连接 OpenAI 模型&#xff0c;设置 API 密钥&#xff0c;并使用 Spring AI 的 ChatClient 与 OpenAI 模型进行简单的对话。Spring AI 为集成 OpenAI 模型提供了方便的工具&#xff0c;使得开发者能够更轻松地与 GPT 系列模型进行交互。 …

CMake常用命令指南(CMakeList.txt)

CMakeList从入门到精通的文章有很多不再赘述&#xff08; 此处附带一篇优秀的博文链接&#xff1a;一个简单例子&#xff0c;完全入门CMake语法与CMakeList编写 &#xff09;。 本文主要列举 CMake 中常用命令的详细说明、优缺点分析以及推荐做法&#xff0c;以更好地理解和灵…

zsh安装插件

0 zsh不仅在外观上比较美观&#xff0c;而且其具有强大的插件&#xff0c;如果不使用那就亏大了。 官方插件库 https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins 官方插件库并不一定有所有的插件&#xff0c;比如zsh-autosuggestions插件就不再列表里&#xff0c;下面演示zs…

消息队列篇--通信协议篇--应用层协议和传输层协议理解

在网络通信中&#xff0c;传输层协议和应用层协议是OSI模型中的两个不同层次的协议&#xff0c;它们各自承担着不同的职责。 下文中&#xff0c;我们以TCP/UDP&#xff08;传输层协议&#xff09;和HTTP/SMTP&#xff08;应用层协议&#xff09;为例进行详细解释。 1、传输层协…

Linux - 进程间通信(2)

目录 2、进程池 1&#xff09;理解进程池 2&#xff09;进程池的实现 整体框架&#xff1a; a. 加载任务 b. 先描述&#xff0c;再组织 I. 先描述 II. 再组织 c. 创建信道和子进程 d. 通过channel控制子进程 e. 回收管道和子进程 问题1&#xff1a; 解答1&#xff…

安全漏洞扫描与修复系统的高质量技术详解

安全漏洞扫描与修复系统的高质量技术详解 在当今的数字化时代&#xff0c;网络安全已成为企业和个人不可忽视的重要议题。安全漏洞扫描与修复系统作为保障网络安全的关键环节&#xff0c;其重要性日益凸显。本文将深入探讨安全漏洞扫描与修复系统的原理、流程、工具选择以及实…

基于Django的豆瓣影视剧推荐系统的设计与实现

【Django】基于Django的豆瓣影视剧推荐系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用了Python作为后端开发语言&#xff0c;采用Django作为后端架构&#xff0c;结…

【Rust自学】15.7. 循环引用导致内存泄漏

说句题外话&#xff0c;这篇文章真心很难&#xff0c;有看不懂可以在评论区问&#xff0c;我会尽快作答的。 喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω…

Blazor-Blazor Web App项目结构

让我们还是从创建项目开始&#xff0c;来一起了解下Blazor Web App的项目情况 创建项目 呈现方式 这里我们可以看到需要选择项目的呈现方式&#xff0c;有以上四种呈现方式 ● WebAssembly ● Server ● Auto(Server and WebAssembly) ● None 纯静态界面静态SSR呈现方式 WebAs…

Bootstrap 简介

Bootstrap 简介 Bootstrap 是一个流行的前端框架,它可以帮助开发者快速构建响应式、移动优先的网站和应用程序。自 2011 年发布以来,Bootstrap 已经成为全球范围内最受欢迎的前端开发工具之一。本文将详细介绍 Bootstrap 的概念、特点、安装和使用方法。 Bootstrap 概念 B…

登录授权流程

发起一个网络请求需要&#xff1a;1.请求地址 2.请求方式 3.请求参数 在检查中找到request method&#xff0c;在postman中设置同样的请求方式将登录的url接口复制到postman中&#xff08;json类型数据&#xff09;在payload中选择view parsed&#xff0c;将其填入Body-raw中 …

pytorch使用SVM实现文本分类

完整代码&#xff1a; import torch import torch.nn as nn import torch.optim as optim import jieba import numpy as np from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import TfidfVectorizer from sklearn import metric…

【硬件介绍】三极管工作原理(图文+典型电路设计)

什么是三极管&#xff1f; 三极管&#xff0c;全称为双极型晶体三极管&#xff0c;是一种广泛应用于电子电路中的半导体器件。它是由三个掺杂不同的半导体材料区域组成的&#xff0c;这三个区域分别是发射极&#xff08;E&#xff09;、基极&#xff08;B&#xff09;和集电极&…

51单片机开发:串口通信

实验目标&#xff1a;电脑通过串口将数据发送给51单片机&#xff0c;单片机原封不动地将数据通过串口返送给电脑。 串口的内部结构如下图所示&#xff1a; 串口配置如下&#xff1a; TMOD | 0X20 ; //设置计数器工作方式 2 SCON 0X50 ; //设置为工作方式 1 PCON 0X80 ; …

DeepSeek-R1本地部署笔记

文章目录 效果概要下载 ollama终端下载模型【可选】浏览器插件 UIQ: 内存占用高&#xff0c;显存占用不高&#xff0c;正常吗 效果 我的配置如下 E5 2666 V3 AMD 590Gme 可以说是慢的一批了&#xff0c;内存和显卡都太垃圾了&#xff0c;回去用我的新设备再试试 概要 安装…

Linux 命令之技巧(Tips for Linux Commands)

Linux 命令之技巧 简介 Linux ‌是一种免费使用和自由传播的类Unix操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹&#xff08;Linus Benedict Torvalds&#xff09;于1991年10月5日首次发布。Linux继承了Unix以网络为核心的设计思想&#xff0c;是一个性能稳定的多用户…

【愚公系列】《循序渐进Vue.js 3.x前端开发实践》029-组件的数据注入

标题详情作者简介愚公搬代码头衔华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xff0c;腾讯云优秀博主&…

deepseek-r1 本地部署

deepseek 最近太火了 1&#xff1a;环境 win10 cpu 6c 内存 16G 2: 部署 1>首先下载ollama 官网&#xff1a;https://ollama.com ollama 安装在c盘 模型可以配置下载到其他盘 OLLAMA_MODELS D:\Ollama 2>下载模型并运行 ollama run deepseek-r1:<标签> 1.5b 7b 8…

租赁系统为企业资产管理提供高效解决方案促进业务增长与创新

内容概要 在现代商业环境中&#xff0c;企业不断寻求高效的管理解决方案&#xff0c;以提高运营效率、降低成本并推动业务增长。而租赁系统正是一款理想的工具&#xff0c;能够帮助企业实现这一目标。 快鲸智慧园区(楼宇)管理系统作为数字化资产管理的领先选择&#xff0c;提供…