指针数组以及利用函数指针来实现简易计算器及typedef关键字(指针终篇)

本文主要是介绍指针数组以及利用函数指针来实现简易计算器及typedef关键字(指针终篇),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

请添加图片描述

文章目录

  • 🚀前言
  • 🚀两段有趣的代码
    • ✈️typedef关键字
  • 🚀指针数组
  • 🚀简易计算器的实现

🚀前言

基于阿辉前两篇博客指针的基础篇和进阶篇对于指针的了解,那么今天阿辉将为大家介绍C语言的指针剩下的部分,包括指针数组以及利用函数指针来实现简易计算器及typedef关键字,关注阿辉不迷路哦 😘 ,内容干货满满😋,接下来就跟着阿辉一起学习吧👊

🚀两段有趣的代码

以下两段代码出自于《C陷阱和缺陷》这本书,这两段代码有一定的难度,需要有一定的指针基础否则可能看不懂,看不懂的可以翻看阿辉前两篇关于指针的博客。
代码1

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

这段代码确实变态,铁子们别急,让我们分析一下:
1.首先,代码( *( void ( * )())0 )()右边单独的括号()很明显它是函数调用操作符,说明( *( void ( * )())0 )这一大坨代表一个函数名
2.然后,void ( * )()这一坨,铁子们这玩意不就是函数指针类型嘛,被指向函数返回类型是void没有参数, void ( * )()这玩意外面套个括号不就是(类型)强制类型转换嘛

那这不就简单了,不就是把数字0强制转化成一个函数指针,然后解引用调用该函数

代码2

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

void (*signal(int , void(*)(int)))(int)这一坨我们咋一看很懵,不过我要是把这个signal(int , void(*)(int))拎出来铁子们肯定熟,这玩意怎么这么像函数声明,铁子们大胆点,你们看看void (*)(int)这一部分不就是函数指针类型吗,这俩一结合不就是函数声明嘛

signal是函数名,它的两个参数类一个是int,一个是返回值为void参数为int的函数指针类型,然后signal的返回类型也是一个返回值为void参数为int的函数指针类型

这里你可能会想这段码难写可读性还差,其实有解决方法,铁子们咱继续👇

✈️typedef关键字

通过typedef,可以为已有的数据类型定义一个新的名字,使得代码更易读、更易维护
语法格式为:

typedef 类型名 新类型名

例子:

 typedef unsigned int size_t;size_t a;对于size_t创建的变量a其实就是unsigned int类型的

对于指针类型,新类型名必须在*右边
例子:

 typedef int(*parr_t)[5];typedef void(*pfun_t)(int);void (*signal(int , void(*)(int)))(int);对于上面这段函数我们就可以这么写了pfun_t signal(int , pfun_t);可读性直接提升一大截

🚀指针数组

铁子们都知道,数组是自定义类型,前面咱们学了指针的一系列类型,这不咱们数组又添一个大家族——指针数组,指针数组顾名思义是存放指针的数组
指针数组的创建

type* name[const];
name是数组名
const是常量给定数组大小
type*是数组的类型

注意这里要与数组指针区分开,由于[]的优先级高于*,所以type* name[const]name[]先结合表明name是指针,而数组指针type (*name)[const](*name)确保*name先结合表明name是指针
举个栗子👇

int* a1[10];//存放整型指针的指针数组
char* a2[10];//存放字符指针的指针数组
int(*a3[10])[5];//存放数组指针的数组指针数组
int(*a4[10])(int);//存放函数指针的函数指针数组

指针数组有什么用呢?铁子们不要急我们接着看👇

🚀简易计算器的实现

利用switch来实现简易计算器
简易计算器的实现思路:

  • 内置加减乘除四种运算
  • 打印菜单供用户选择运算方式以及退出计算器
  • 输入待计算的数字
  • 输出计算结果
#include <stdio.h>
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 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;
}int main()
{int x, y;int input = 1;int ret = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input)//选择{case 1:printf("输入两个操作数:");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("输入两个操作数:");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("输入两个操作数:");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("输入两个操作数:");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;
}

上面的这段利用switch实现的代码,有大量重复的元素导致代码极为臃肿,而且对于后期代码的维护也是极为不便,这里我们观察发现add,sub,mul,div这四个函数有着同样的参数以及返回类型,这有什么用呢?铁子们我们接着看
我们完全可以,创建一个函数指针数组来存放他们

int (*a[])(int,int) = {add,sub,mul,div};

有了这个函数指针数组,我们只需要输入下标便可以通过a[input](x,y)来调用函数,但是下标并没有与菜单对应起来,很简单仅需要在数组里面添一个NULL就行int (*a[])(int,int) = {NULL,add,sub,mul,div}
在这里插入图片描述
然后一堆的switch case语句简化成:

	if (input == 0){printf("退出计算器\n");}else if (input >= 1 && input <= 4){										printf("请输入两个操作数:");scanf("%d %d", &x, &y);ret = pfArr[input](x, y);         printf("%d\n", ret);}else{printf("选择错误,重新选择\n");}

不得不说设计C语言的人真的是厉害,后面如果要添加其他运算仅仅只用添函数改一下菜单以及把数组名加到数组里面就行了,绝真的绝!!!


到这里,阿辉今天对于C语言中指针部分的分享就结束了,希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,你们的支持是我创作的最大动力🌹

请添加图片描述

这篇关于指针数组以及利用函数指针来实现简易计算器及typedef关键字(指针终篇)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/441205

相关文章

pandas中位数填充空值的实现示例

《pandas中位数填充空值的实现示例》中位数填充是一种简单而有效的方法,用于填充数据集中缺失的值,本文就来介绍一下pandas中位数填充空值的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是中位数填充?为什么选择中位数填充?示例数据结果分析完整代码总结在数据分析和机器学习过程中,处理缺失数

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Pandas使用AdaBoost进行分类的实现

《Pandas使用AdaBoost进行分类的实现》Pandas和AdaBoost分类算法,可以高效地进行数据预处理和分类任务,本文主要介绍了Pandas使用AdaBoost进行分类的实现,具有一定的参... 目录什么是 AdaBoost?使用 AdaBoost 的步骤安装必要的库步骤一:数据准备步骤二:模型

使用Pandas进行均值填充的实现

《使用Pandas进行均值填充的实现》缺失数据(NaN值)是一个常见的问题,我们可以通过多种方法来处理缺失数据,其中一种常用的方法是均值填充,本文主要介绍了使用Pandas进行均值填充的实现,感兴趣的... 目录什么是均值填充?为什么选择均值填充?均值填充的步骤实际代码示例总结在数据分析和处理过程中,缺失数

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

python实现svg图片转换为png和gif

《python实现svg图片转换为png和gif》这篇文章主要为大家详细介绍了python如何实现将svg图片格式转换为png和gif,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录python实现svg图片转换为png和gifpython实现图片格式之间的相互转换延展:基于Py

Python利用ElementTree实现快速解析XML文件

《Python利用ElementTree实现快速解析XML文件》ElementTree是Python标准库的一部分,而且是Python标准库中用于解析和操作XML数据的模块,下面小编就来和大家详细讲讲... 目录一、XML文件解析到底有多重要二、ElementTree快速入门1. 加载XML的两种方式2.

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组