【c语言】指针就该这么学(3)

🌟🌟作者主页:ephemerals__

🌟🌟所属专栏:C语言

目录

一、函数指针

1.函数指针变量的创建

2.函数指针变量的使用

二、typedef关键字

三、函数指针数组

1.函数指针数组的概念        

2.函数指针数组的定义方式

四、转移表

总结


一、函数指针

        在c语言中,不仅有变量的指针,也有函数指针。与变量相同,函数指针存放的是函数的地址,通过函数的地址可以调用该函数

1.函数指针变量的创建

        函数指针的创建方法如下:

类型1 (*变量名)(类型2,类型3......);

与数组指针的定义方式一样,函数指针的变量名也是需要先和*号结合的。不同的是,之后的方括号变成了圆括号。详细说明一下这里的要点:

类型1指的是函数指针指向函数的返回值类型;

类型2、类型3等等都是指向函数的参数类型,参数的数量和类型要和函数的参数保持一致,类型之后的形参名可写可不写。

接下来让我们尝试定义一个函数指针变量,存放函数的地址:

#include <stdio.h>int add(int a, int b)
{return a + b;
}int main()
{int a = 3;int b = 5;int (*pf1)(int, int) = add;int (*pf2)(int, int) = &add;return 0;
}

注意:以上代码中,pf1和pf2存放的是完全相同的地址。对于函数来讲,函数名之前是否加取地址符号都表示函数的地址,所以&可写可不写。

2.函数指针变量的使用

接下来我们尝试通过函数指针来调用函数:

#include <stdio.h>int add(int a, int b)
{return a + b;
}int main()
{int a = 3;int b = 5;int (*pf)(int, int) = add;int ret = pf(a, b);//指针变量的使用printf("%d\n", ret);return 0;
}

这里使用pf接收了add函数的地址,pf就等价于add,直接传参就可以调用函数。

二、typedef关键字

        我们学习了复杂的指针类型(例如数组指针、函数指针)之后,会发现它们的定义方式较为复杂。那么是否有办法能够让我们简化定义的代码呢?这就需要用到typedef关键字了。

typedef是c语言中的一个关键字,它用于对类型进行重定义,将复杂的类型简单化。

它的使用方法是:

typedef 类型1 类型2;

进行typedef操作之后,类型2与类型1就是等价的。

接下来我们尝试将一些变量类型进行重定义:

#include <stdio.h>typedef int t;//类型重定义t main()
{t a = 0;printf("%d\n", a);return 0;
}

运行结果:

这里我们将int类型重定义了一个名字叫 t ,之后的使用当中定义的整形类型都可以用 t 来表示。

对于指针变量,我们也可以这样重定义:

#include <stdio.h>typedef int* ptr_t;int main()
{int a = 0;ptr_t p = &a;printf("%p\n", p);return 0;
}

运行结果:

可以看到,程序输出了一个地址,我们将整形指针变量重新起名为ptr_t。

接着,我们尝试对数组指针和函数指针类型重定义:

可以看到,对于数组指针或者函数指针类型重定义时,这种语法是不正确的,我们要将新类型名写到*号旁边

这样,对于一些复杂类型的数组指针或者函数指针,我们就可以用简单的单词来表示。

三、函数指针数组

1.函数指针数组的概念        

我们都知道,指针数组就是数组元素都是指针变量。而函数指针数组就是说这个数组当中的元素类型都是函数指针

2.函数指针数组的定义方式

函数指针数组的定义方式如下:

类型1 (*变量名[元素个数])(类型2,类型3......);

从它的定义方式可以看出,函数指针数组的定义方式就是在函数指针的变量名后加上方括号。这里变量名和[]先结合,说明它是一个数组,而数组的元素就是函数指针类型。代码示例:

#include <stdio.h>void test1()
{printf("hehe\n");
}void test2()
{printf("haha\n");
}void test3()
{printf("hello\n");
}int main()
{void (*pfarr[3])() = { test1,test2,test3 };//函数指针数组的定义和初始化int num = 0;while (scanf("%d", &num) != EOF){pfarr[num - 1]();}return 0;
}

运行结果:

不难看出,程序就可以根据输入的值来调用不同的函数

注意:我们在使用函数指针数组时,函数指针数组所指向的所有函数的类型必须一致。

四、转移表

        刚才我们简单使用了一下函数指针数组,这种通过函数指针数组来实现的调用不同函数的方法叫做转移表。由于计算器这类程序可以有多种运算功能,我们就运用转移表来实现一个简单的计算器。

程序代码:

#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;
}int main()
{int(*pfarr[5])(int, int) = { NULL,add,sub,mul,div };int input = 0;do{printf("************************\n");printf("***  1.add    2.sub  ***\n");printf("***  3.mul    4.div  ***\n");printf("***  5.exit ************\n");printf("************************\n");printf("请选择:>>>");scanf("%d", &input);if (input >= 1 && input <= 5){int a = 0;int b = 0;printf("请输入两个操作数:>>>");scanf("%d %d", &a, &b);printf("结果是:%d\n",pfarr[input](a, b));}else if (input == 0){printf("退出计算器\n");}else{printf("输入错误!请重新输入!");}} while (input);return 0;
}

当我们使用转移表时,就可以在功能过多的情况下免去使用switch语句和大量的case语句,使得代码更加简洁

总结

        这篇文章我们学习了函数指针,typedef关键字和函数指针数组等知识和应用。之后博主会和大家介绍c语言中的库函数--qsort,并且模拟实现。如果你觉得博主讲的还不错,就请留下一个小小的赞在走哦,感谢大家的支持❤❤❤

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

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

相关文章

$nextTick的使用场景介绍

$nextTick使用 Vue更新DOM-异步的 目标: 点击count, 马上通过"原生DOM"拿标签内容, 无法拿到新值 components/Move.vue - 继续新增第三套代码 <template><div><p>1. 获取原生DOM元素</p><h1 id"h" ref"myH">我是…

从零开始实现自己的串口调试助手(8)-循环发送

循环发送 准备 创建槽函数 设置QSpinBox的最大值 注意&#xff1a; // 我们不能在qt的ui线程中延时&#xff0c;否则将导致页面刷新问题 //QThread::msleep(ui->spinBox->text().toInt());//设置下次发送时间间隔 定时器实现 关联信号与槽: //添加自动换行定…

centos中sudo: apt: command not found

系统找不到apt这个命令。CentOS中应该使用sudo yum或sudo dnf&#xff08;CentOS 8及以后版本&#xff09;来执行包管理操作。不建议安装使用apt&#xff0c;可能会破坏系统的稳定性和兼容性。建议使用sudo yum install package_name来安装软件包。

Pycharm创建Conda虚拟环境时显示CondaHTTPErOT

原因&#xff1a;conda源出问题了&#xff0c;之前可以用&#xff0c;现在报错。 最好的解决方案&#xff1a;找到conda源&#xff0c;换源即可。 步骤&#xff1a; 1.修改 .condarc 文件&#xff08;文件的位置在&#xff1a;C:\Users\(你的用户名)\.condarc&#xff09;&a…

Python中的@staticmethod和@classmethod装饰器

名词解释 本文主要介绍静态方法staticmethod和类方法classmethod在类中的应用&#xff0c;在介绍这两个函数装饰器之前&#xff0c;先介绍类中的几个名词&#xff0c;便于后面的理解&#xff1a; 类对象&#xff1a;定义的类就是类对象 类属性&#xff1a;定义在__init__ 外…

type 相关的几个试验

1.概要 typeid是一个操作符&#xff0c;它用于在运行时获取关于数据类型的信息。 在C语言中&#xff0c;类型定义&#xff08;Type Definition&#xff09;通常是通过使用关键字如 typedef 来创建新的类型名称&#xff08;也称为类型别名&#xff09;&#xff0c;这些新的类型…

基于自动化工具autox.js的抢票(猫眼)

1.看到朋友圈抢周杰伦、林俊杰演唱会票贼难信息&#xff0c;特研究了一段时间&#xff0c;用autox.js写了自动化抢票脚本&#xff0c;购票页面自动点击下单&#xff08;仅限安卓手机&#xff09;。 2.脚本运行图 3.前期准备工作 &#xff08;1&#xff09;autox.js社区官网&am…

DNF手游攻略:主C职业推荐,云手机强力辅助!

在《地下城与勇士》手游中&#xff0c;你是否厌倦了重复刷图和无休止的手动操作&#xff1f;利用VMOS云手机&#xff0c;你可以一键解决这些烦恼&#xff0c;实现自动打怪、一机多开&#xff0c;让游戏变得更加轻松愉快。下面我们将介绍如何使用VMOS云手机&#xff0c;以及推荐…

卫生间装修10个避坑细节

雅静说卫生装修,记住这10条不后悔      卫生间装不好,漏水,臭,很麻烦      1先检查下水管,防止小黑虫和漏水      它里面必须要有皮垫密封圈,,看完以后把它拧紧      防止后期漏水还得砸瓷砖      2,改水电的时候留够插座,马桶一个      浴室柜的灯提前…

0109__strip(1) command

strip(1) command_linux strip-CSDN博客

MySQL-Explain使用

MySQL-Explain使用 type列 type列 这一列表示关联类型或访问类型&#xff0c;即MySQL决定如何查找表中的行&#xff0c;查找数据行记录的大概范围。 依次从最优到最差分别为&#xff1a;system > const > eq_ref > ref > range > index > ALL 一般来说&…

现代信号处理复习笔记(一)简答题

本文仅作为复习参考。 1、简述卡尔曼滤波和维纳滤波的关系。 在线性时不变系统和加性白噪声的情况下,卡尔曼滤波进入稳态值之后,等价于因果的维纳滤波。在一些情况下,卡尔曼滤波的状态更新方程和协方差更新方程与维纳滤波的滤波方程是一致的,因此可以将卡尔曼滤波看作是维…

Python入门!这些你都知道吗?

Python的基本介绍 Python是由荷兰人吉多范罗苏姆&#xff08;Guido van Rossum&#xff09;于1990年代初设计的一门编程语言&#xff0c;作为ABC语言的替代品。它提供了高效的高级数据结构&#xff0c;并且能简单有效地进行面向对象编程。Python的语法简洁、易读&#xff0c;并…

rk3568 norflash+pcei nvme 配置

文章目录 rk3568 norflashpcei nvme 配置1&#xff0c;添加parameter_nor.txt文件2 修改编译规则3 修改uboot4 修改BoardConfig.mk5 修改kernel pcei配置6 编译7 烧录 rk3568 norflashpcei nvme 配置 1&#xff0c;添加parameter_nor.txt文件 device/rockchip/rk356x/rk3568_…

查询数据库每张表的记录数和数据大小的方法(不含索引)

1、手残方法 自己写脚本&#xff0c;不会利用元数据表和只会简单sql的解决办法&#xff1a; # cat loop_db_tables.sh #!/bin/bashdbnamesmysql -uroot -ppassword -e "show databases;" for dbname in $dbnames do# 由于是借用了shell&#xff0c;所以需要处理输…

git commit rule

git commit rule feat: 新功能 fix: bug修复 docs: 仅文档更改 style: 不影响代码含义的更改&#xff08;空白、格式设置、缺失 分号等&#xff09; refactor: 既不修复bug也不添加特性的代码更改 perf: 改进性能的代码更改 test: 添加缺少的测试或更正现有测试 chore: 对构建…

【学习笔记】Windows GDI绘图(十三)动画播放ImageAnimator(可调速)

文章目录 前言定义方法CanAnimate 是否可动画显示Animate 动画显示多帧图像UpdateFramesStopAnimate终止动画Image.GetFrameCount 获取动画总帧数Image.GetPropertyItem(0x5100) 获取帧延迟 自定义GIF播放(可调速) 前言 在前一篇文章中用到ImageAnimator获取了GIF动画的一些属…

vue3 监听器,组合式API的watch用法

watch函数 在组合式 API 中&#xff0c;我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数 watch(ref,callback&#xff08;newValue,oldValue&#xff09;&#xff0c;option:{}) ref:被监听的响应式量&#xff0c;可以是一个 ref (包括计算属性)、一个响应式…

STM32—按键控制LED(定时器)

目录 1 、 电路构成及原理图 2 、编写实现代码 main.c exit.c 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 EXTI&#xff08;External interrupt/event controller&#xff…

查询SQL02:寻找用户推荐人

问题描述 找出那些 没有被 id 2 的客户 推荐 的客户的姓名。 以 任意顺序 返回结果表。 结果格式如下所示。 题目分析&#xff1a; 这题主要是要看这null值会不会用&#xff0c;如果说Java玩多了&#xff0c;你去写SQL时就会有问题。在SQL中判断是不是null值用的是is null或…