指针(4)有点难

指针(4)

来做个简单的回顾:

指针数组

1.是数组
2.是存放指针的数组

char* arr1[5];

int*arr2[3];

数组指针

1 .是指针
2 .指向数组的指针

字符指针:char*pc;

整型指针:int*pi;

int (*p) [10];//P就是数组指针,p指向的数组有10个元素,每个元素的类型是int
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{int arr[10] = { 0 };int(*p)[10] = &arr;//取的是整个数组的地址return 0;
}

例子

想使用p这个数组访问arr数组的内容

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;//取的是整个数组的地址int i = 0;
for (i = 0; i <= 10; i++)
{printf("%d", p[i]);//*(p+i)
}

1 .二维数组传参的本质

代码如下:

void Print(int arr[3][5], int r, int c)//int (*arr)[5]
{int i = 0;for (i = 0; i <=r; i++){for (int j = 0; j <=c; j++){printf("%d", arr[i][j]);//*(*(arr+i)+j)//*(arr+i)==arr[i]//arr[i]是第i行的数组名,数组名又是数组首元素的地址,arr[i]=&arr[i][0]}printf("\n");}
}int main()
{int arr[3][5] = { (1,2,3,4,5),(2,3,4,5,6),(3,4,5,6,7) };Print(arr, 3, 5);return 0;
}

前情回顾

一维数组传参

数组名是首元素的地址,一维数组传参的时候,其实传递的是首元素的地址。

函数的参数可以写成数组,也可以写成指针。

那二维数组呢?

其实二维数组的数组名也是数组首元素的地址,二维数组的数组名就是它第一行的地址,第一行是一个一维数组,传过去的是第一行这个一维数组的地址

[外链图片转存中…(img-Lf2wiLHP-1715345940161)]

[外链图片转存中…(img-HzRavJos-1715345940162)]

总结

arr[i]==*(arr+i)

arr[i] [j]=* (*(arr+i)+j)

不管是一维数组还是二维数组,形参可以写成数组,也可以写成指针,这里要对数组名做深入理解

2 .函数指针变量

void Add(int x, int y)
{return x + y;
}int main()
{int a = 2;int b = 6;Add(a, b);printf("%p\n", &Add);return 0;
}

运行结果:

[外链图片转存中…(img-lowcQ39K-1715345940163)]

小小的不同

&函数名和函数名的地址没有不同

[外链图片转存中…(img-815uKMMu-1715345940163)]

[外链图片转存中…(img-1Si0XL6D-1715345940163)]

函数指针变量的注意点

我们之前学习调用函数的时候

形式如下:

int ret2 = Add(4, 5);

其实函数指针变量也可以写成另外一种形式,也是可以的:

int ret3 = pf(4, 5);

但是写上*的时候,不要忘记加(),因为这时候pf会和(4,5)相结合,调用的·是函数值的地址,这就有问题了

函数指针类型解析:

int (*pf3) (int x, int y)
|     | ------------
|     |         |
|     |     pf3指向函数的参数类型和个数的交代
|   函数指针变量名
pf3指向函数的返回类型
int (*) (int x, int y) //pf3函数指针变量的类型

3 .两段有趣的代码

代码1:

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

[外链图片转存中…(img-pL9wxN6Q-1715345940163)]

代码2:

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

[外链图片转存中…(img-FNyDCtyc-1715345940164)]

[外链图片转存中…(img-3hjNYgd0-1715345940164)]

可以这样理解,但是语法不允许这样写

4 .typedef关键字

typedef unsigned int unit;
int main()
{unsigned int num;unit num;return 0;
}

对数组指针重命名:

typedef int(*parr_t)[10]//一定要把指针放里面
int main()
{int arr[6] = { 0 };int(*p) = &arr;parr_t p2 = &arr;return 0;
}

对函数指针重命名:

int Add(int x, int y)
{return x + y;
}
typedef int(*pf_t)(int, int);int main()
{int(*pf)(int, int) = Add;pf_t pf2 = Add;return 0;
}

那么我们在有趣的代码这一节中那个函数的声明也可以写成:

typedef void(*pf_t)(int)int main()
{pf_t signal(int,pf_t);return 0;
}

5 .函数指针数组

int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Plus(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int(*pf[4])(int,int) = {Add,Sub,Plus,Div};//函数指针数组//0,  1  ,2  ,3int i=0;for(i=0;i<4;i++){int ret=pf[i](6,2);printf("%d\n",ret);
}return 0;
}

6 .转移表

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

例子:计算器

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void menu(){printf("**************************\n");printf("*******1 .Add 2 .Sub******\n");printf("*******3 .Plus4 .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 Plus(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);int(*prArr[5])(int,int) = {0,Add,Sub,Plus,Div};//函数指针数组if (input >= 1 && input <= 4){printf("请输入两个操作数:");scanf("%d %d", &x, &y);ret = prArr[input](x, y);printf("%d\n", ret);}if (input == 0){printf("您已退出计算器\n");}else{printf("请重新做选择\n");}} while (input);return 0;
}

7 .回调函数是什么?

回调函数就是⼀个通过函数指针调⽤的函数。

如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条 件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。

[外链图片转存中…(img-wA8XZowf-1715345940164)]

ret);
}
if (input == 0)
{
printf(“您已退出计算器\n”);
}
else
{
printf(“请重新做选择\n”);
}
} while (input);

return 0;

}


## 7 .回调函数是什么?回调函数就是⼀个通过函数指针调⽤的函数。如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条 件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。[外链图片转存中...(img-wA8XZowf-1715345940164)]Calc起到了封装的作用

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

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

相关文章

win10无法被远程桌面连接,Win10系统无法被远程桌面连接的原因有哪些

win10无法被远程桌面连接&#xff0c;Win10系统无法被远程桌面连接的原因有哪些&#xff1f; 先&#xff0c;我们需要明确Win10系统无法被远程桌面连接的可能原因。其中&#xff0c;最常见的原因包括&#xff1a;远程桌面功能未启用、网络连接问题、防火墙或安全软件设置不当、…

哪个牌子的电视盒子好用?小编分享最新电视盒子排名

最近电视盒子是大家热议的话题&#xff0c;就目前来看它的地位依然无可替代&#xff0c;但许多朋友硬不知道哪个牌子的电视盒子好用&#xff0c;面对众多品牌和产品究竟要如何选择才是最好的呢&#xff1f;本期小编要分享最新发布的电视盒子排名&#xff0c;看看哪些电视盒子最…

C++ 抽象与封装

一 抽象 抽象实例&#xff1a;时钟 数据抽象&#xff1a; 具有表面当前时间的时、分、秒 行为抽象&#xff1a; 具有设置时间和显示时间两个最基本的功能。 抽象实例&#xff1a;人 数据抽象&#xff1a;姓名、年龄、性别等。 行为抽象&#xff1a; 生物属性&#xff1a;吃…

【线性代数】英语版听课笔记

线性代数 - 北京航天航空大学&#xff08;英文版&#xff09;_哔哩哔哩_bilibili 39.concept of vector space in this lecture we will studyvector space&#xff0c; the concept of basis dimension and coordinates 向量空间的维数&#xff1a;向量空间的基底所含向量的…

TCP超时重传机制

一、TCP超时重传机制简介 TCP超时重传机制是指当发送端发送数据后&#xff0c;如果在一定时间内未收到接收端的确认应答&#xff0c;则会认为数据丢失或损坏&#xff0c;从而触发重传机制。发送端会重新发送数据&#xff0c;并等待确认应答。如果在多次重传后仍未收到确认应答&…

车载测试__公司面试题(整理)

案例1&#xff1a; 镁佳 外包岚图汽车 车载测试 区域经理视频面试 1.首先自我介绍一下 2.项目是怎么测的举例说明 3.你是怎么看待加班的 4.你是怎么看待驻场单位 5.是否可以接受外派去做一段时间的技术支持&#xff0c;比如去襄阳&#xff0c;最长一个月。 6.多快能到…

Codigger:优化Vim编辑器的关键是可视化

Vim是一款高度灵活的文本编辑器&#xff0c;以其高效的快捷键和命令行界面而闻名。然而&#xff0c;对于一些初学者来说&#xff0c;Vim的复杂性和强大的功能可能会让他们感到困惑。为了使Vim更易于使用&#xff0c;Codigger引入可视化操作的概念&#xff0c;将原本抽象的、难以…

初步了解json文件

来自wetab 的AI pro: JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式&#xff0c;但是它使用了类似于编程语言&#xff08;特别是J…

智慧公厕,运用数据提升公共厕所管理水平!

随着城市人口的增加和生活水平的提高&#xff0c;公共厕所的管理变得越来越重要。传统的厕所管理方式已经无法满足人们对卫生、便利和舒适的需求。而智慧公厕作为新一代公厕管理方式&#xff0c;通过运用数据技术和大数据分析手段&#xff0c;彻底改变了公厕管理的模式&#xf…

Maximo 在 Automation Script 中访问数据库

在 Automation Script 中我们通常使用 mbo 对象来操作数据&#xff0c;但有时候当数据量较大时&#xff0c;使用 mbo 对象来操作数据会比较慢。这时候&#xff0c;我们可以使用 JDBC 的方式来直接访问数据库&#xff0c;从而提高操作数据的效率。 下面看看使用 JavaScript 脚本…

2024OD机试卷-执行任务赚积分 (java\python\c++)

题目:执行任务赚积分 题目描述 现有N个任务需要处理,同一时间只能处理一个任务,处理每个任务所需要的时间固定为1。 每个任务都有最晚处理时间限制和积分值,在最晚处理时间点之前处理完成任务才可获得对应的积分奖励。 可用于处理任务的时间有限,请问在有限的时间内,可…

C++对象的赋值

同类的对象之间可以互相赋值&#xff0c;即一个对象的值可以赋值给另一个对象。对象之间的赋值通过“”进行。默认就是把一个对象所有非static数据成员的值依次赋值给另一个对象。 对象赋值的一般形式为&#xff1a; 对象名1 对象名2; 注意:对象名1和对象名2必须是属于同一个…

flutter开发实战-GetX响应式状态管理使用

flutter开发实战-GetX响应式状态管理使用 GetX是一个简单的响应式状态管理解决方案。GetX是Flutter的一款超轻、功能强大的解决方案。它将高性能状态管理、智能依赖注入和路由管理快速而实用地结合在一起。这里简单使用一下GetX 一、引入GetX 在工程的pubspec.yaml中引入插件…

信息系统架构模型_1.单机应用模式和客户机/服务器模式

1.单机应用模式&#xff08;Standalone&#xff09; 单机应用系统是最简单的软件结构&#xff0c;是指运行在一台物理机器上的独立应用程序。这些软件系统&#xff0c;从今天的软件架构上来讲&#xff0c;是很简单&#xff0c;是标准的单机系统。当然至今&#xff0c;这种复杂的…

export QT_DEBUG_PLUGINS=1

Qt的编程中包含了插件模式&#xff0c;使得程序的扩展性非常好&#xff0c;但插件的动态加载的检查也比较严格&#xff0c;这次编译数据库驱动插件就碰到了不少问题。实际上&#xff0c;可以在系统的 环境变量中设置QT_DEBUG_PLUGINS&#xff1d;1 &#xff0c;即在终端中执行 …

电路板维修【二】

【维修一个65W的氮化镓快充头&#xff0c;摔地上就没输出了&#xff0c;看下怎么回事】&#xff1a;https://www.bilibili.com/video/BV1vG411Q7MDvd_source3cc3c07b09206097d0d8b0aefdf07958 对于某些电器&#xff0c;维修之前需要先测量主滤波电容上面有没有存电&#xff0c…

【java】泛型

文章目录 1. 什么是泛型&#xff1f;1.1 背景1.2 泛型的概念1.3 泛型的好处 2. 泛型类、接口...2.1 泛型类2.2 从泛型类派生子类2.2.1 子类也是泛型类&#xff0c;子类和父类的泛型类型要一致2.2.2 子类不是泛型类&#xff0c;父类要明确泛型的数据类型 2.3 泛型接口2.4 泛型方…

【AMBA Bus ACE 总线 8 -- ICache maintenance】

请阅读【AMBA Bus ACE 总线与Cache 专栏 】 欢迎学习:【嵌入式开发学习必备专栏】 文章目录 ACE ICache maintenanceACE ICache maintenance 图 1-1 当一个OS run 多个cpu的时候,根据调度算法的不同,OS 可以根据调度算法的不同分别 run 在某个具体的CPU上,因此,它们会有…

分布式模式让业务更高效、更安全、更稳定

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#x1f525;&#xff1a;探索设计模式的魅力&#xff1a;分布式模…

centos7下安装配置nginx

1、下载nginx安装包 wget http://nginx.org/download/nginx-1.8.0.tar.gz 2、安装nginx所需依赖 yum -y install pcre pcre-devel yum -y install zlib zlib-devel yum -y install openssl openssl-devel 3、进入到nginx安装包目录下&#xff0c;解压tar.gz包 cd /home/soft t…