当前位置: 首页 > news >正文

C语言入门Day_24 函数与指针

目录

前言:

1.指针和数组

2.函数和指针

3.易错点

4.思维导图


前言:

我们知道数组是用来存储多个数据的,以及我们可以用指针来指向一个变量。那么我们可以用指针来指向一个数组中的数据么?

指针除了可以像指向一个变量一样指向一个数组的元素以外,还可以有更灵活的使用方法。

1.指针和数组

1.1

我们先来看看指针如何指向一个数组中的元素

int num_list[5] = {0, 1, 2, 3, 4};
int *p1;
p1 = &num_list[2];
printf("%d\n", *p1);
*p1 = 20;
printf("%d\n", *p1);

1.定义一个有五个整型元素的数组num_list,以及一个整型指针p1

int num_list[5] = {0, 1, 2, 3, 4};

int *p1;

2.把指针指向数组的第三个元素num_list[2],然后打印这个指针指向的数据,输出2

p1 = &num_list[2];

printf("%d\n", *p1);

3.修改这个指针指向的数据,重新赋值20,然后打印这个指针指向的数据,输出20

*p1 = 20;

printf("%d\n", *p1);

1.2

可以看到,把指针指向一个数组的特定元素的使用方式,和把指针指向一个变量的使用方式,是一样的

都是在用指针指向它们的时候:

第一,需要使用取地址符号&来完成给这个指针变量赋值一个内存地址的过程。

第二,需要保证指针的类型和它所指向的数组的类型,是一致的。

1.3

我们把指针数组的第一个元素的地址赋给指针,然后重新给它赋值,并且打印它。

int num_list2[4] = {11, 22, 33, 44};
int *p1;
p1 = &num_list2[0];
*p1 = 111;
printf("%d\n", num_list2[0]);

1.首先初始化一个整型指针p1:

int *p1;

2.把数组第一个元素的内存地址num_list2[0]赋值给指针p1:

p1=&num_list2[0];

1.4

除了把指针指向一个具体的数组元素,我们还可以把指针指向一整个数组!

int num_list[5] = {10, 20, 30, 40, 50};
int *p1;
p1 = num_list;
printf("%d\n", *p1);
printf("%d\n", *(p1+1));

1.定义一个有五个元素的整型数组num_list,和一个整型指针p1

int num_list[5] = {10, 20, 30, 40, 50};

int *p1;

2.把指针指向数组num_list

p1 = num_list;

3.打印指针指向的值,这时候默认打印数组的第一个值num_list[0]

printf("%d\n", *p1);

4.打印指针*(p1+1),这是打印数组的第二个值

printf("%d\n", *(p1+1));

1.5

printf("%d\n",*p1);
printf("%d\n",*(p1+1));

 我们注意到,当用指针指向一个数组的时候,*p就是数组的第一个元素*(p+1)就是数组的第二个元素,同理*(p+2)是数组的第三个元素

为了方便记忆,可以记忆为*(p+0)是数组的第一个元素,*(p+1)是数组的第二个元素,*(p+2)是数组的第三个元素;

指针后面加的数字,等同于数组的下标

1.6

同时,细致的你可能也注意到了指针指向数组的时候,我们是没有使用取地址符&的 

int num_list[5] = {10, 20, 30, 40, 50};
int *p1;
p1 = &num_list[1];
printf("%d\n", *p1);
p1 = num_list;
printf("%d\n", *p1);

1.数组名num_list

int num_list[5] = {10, 20, 30, 40, 50};

2.指针指向单个数组元素的时候有取地址符&

p1 = &num_list[1];

3.指针指向整个数组的时候没有取地址符&

p1 = num_list;

1.6

 这是因为,数组本质上就是一种指针,这也就是说数组名存储的就是一个内存地址,因此把指针指向数组名的过程,也就是把数组名的内存地址赋值给一个指针的过程。

已经是内存地址了,当然就不需要再用取地址符

现在再看*(p+0)是数组的第一个元素,*(p+1)是数组的第二个元素是不是更清楚了,其实我们也可以写成*(num_list+0)*(num_list+1)

由于数组名num_list和指针p都存储的是一个内存地址,所以这两者是等价的。

 1.7

以及指针和数组都需要注意的事也类似,就是数组是有边界的,不能越界访问

比如数组的长度是10,*(p1+20)num_list[20]都是会报错的。

我们学过函数,函数通过参数来接收外界(调用函数的地方)的输入;

通过返回值来向外界(调用函数的地方)输出。

当指针作为函数参数的时候,给函数的这种输入输出机制增加了一个例外

2.函数和指针

 2.1

由于指针指向的一个数据的实际存储的内存地址,因此在函数中对指针指向的数据的修改,是会直接修改到函数外部的变量数据。 

也就是说,指针作为函数参数的时候,即使是在函数内部对指针的数据进行修改,也会穿透到函数外部。

如果说一般函数参数的数据改变,是在函数内部的暂时的改变;

那么指针函数参数的数据改变,就是一种“永久的改变”

2.2

我们来看看指针作为函数参数时候的使用:

void AddThree(int *p1){*p1 = *p1 + 3;
}
int main(){int number_1 = 10;int *p;p = &number_1;AddThree(p);printf("%d\n", *p);
}

 1.定义一个无返回值的函数,且这个函数的参数是一个指针

void AddThree(int *p1){

*p1 = *p1 + 3;

}

2.这是用指针做参数时候的语法

void AddThree(int *p1){         *

3.在main函数中调用这个函数

AddThree(p);

4.需要特别注意的是,传入的是指针(内存地址),而不是指针指向的数据(*p)

AddThree(p);

5.输出计算以后的结果13

printf("%d\n", *p);

2.3

可以看到,虽然函数AddThree()并没有返回值,但是变量number_1的值永久的改变了,这是为什么呢,答案还要回到内存地址上面。

一般的函数参数,只是把一个数据的复制品传入了函数,就像我抄写了一份数据交给你(函数),原始数据还在我(函数外部)这里。

你在函数内部对数据的修改,作用于这个数据的复制品,原始数据是不会改变的。

但是指针作为函数参数的时候,传递给函数的是一个内存地址,你修改了这个内存地址上面的数据,那就是永久的修改。

相当于我把原始数据给你了,而不是给你一个数据的复制品,你在函数内部的操作是直接作用于原始数据的。

2.4 

我们再来看看这张图片,是不是理解会深一点,我们用指针就是在用内存地址,通过对这个内存地址里存储的数据的改变,会永久的修改这个数据;因为它就是原始数据存储的地方

现在我们可能能够更能体会为什么说指针是C语言中很灵活很底层的机制了。

因为有些机制是基于指针的,比如数组数组名

有些机制在使用指针的时候,会方便快捷,甚至打破规则的操作原始数据,比如函数的指针参数

3.易错点

数组本质上也是一个指针

当指针指向整个数组时,不需要到取地址运算符&

但是指针指向数组的某个具体元素时,要用到取地址运算符&

对于一个指向数组的指针p,*(p+0)是数组的第一个元素,*(p+1)是数组的第二个元素,*(p+2)是数组的第三个元素;但是*p+1 是先取出数组第一个元素的值再加1。

4.思维导图

最后我想说的是:

 在撰写这篇文章时,我参考了《白纸编程》这个app的观点和思想,我要感谢他们对我的启发和帮助。

相关文章:

C语言入门Day_24 函数与指针

目录 前言: 1.指针和数组 2.函数和指针 3.易错点 4.思维导图 前言: 我们知道数组是用来存储多个数据的,以及我们可以用指针来指向一个变量。那么我们可以用指针来指向一个数组中的数据么? 指针除了可以像指向一个变量一样指…...

9月21日,每日信息差

今天是2023年9月21日,以下是为您准备的14条信息差 第一、谷歌高管已经广泛讨论了在2027年之前将博通作为人工智能芯片供应商的可能性 第二、清华系团队宣布研发出千亿参数“制药版ChatGPT”,覆盖药物立项、临床前研究、临床试验的各阶段,作…...

【FAQ】安防监控系统/视频云存储/监控平台EasyCVR服务器解释器出现变更该如何修改?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…...

Python手写人脸识别

Python手写人脸识别 引言 人脸识别是一种通过计算机视觉和模式识别技术来识别和验证人脸的技术。Python是一种广泛使用的编程语言,它提供了许多强大的库和工具来实现人脸识别。 在Python中,可以使用多种方法来实现人脸识别,包括基于特征提取的方法、基于深度学习的方法等…...

我的Qt作品(19)使用Qt写一个轻量级的视觉框架---第2章,仿海康VM实现思维导图拖拽方式的算法流程图

上次写的第1章介绍了主界面的设计。 https://blog.csdn.net/libaineu2004/article/details/130277151 本次是第2章,主要介绍流程图的运行。 目前市面上视觉框架很多,主要有列表图方式和流程图方式。海康VM的流程图方式比较受用户的喜爱和欢迎&#xf…...

仿写Timi记账

项目仿照Timi记账,本 APP 仅用作学习,如有侵权联系删除,项目地址:Timi记账 TIMI记账项目 简单功能对于tableview向上延伸部分采用了insertSubview形式:添加特殊字体添加.ttf文件获取plist文件数据 计算器功能说明简单逻…...

Java语言实现 比较两个Date日期的先后

在 Java 中,可以使用 Date 类的 compareTo() 方法或 before()、after() 方法来比较两个 Date 类型的日期的先后顺序。 使用 compareTo() 方法: Date date1 ...; // 第一个日期 Date date2 ...; // 第二个日期int result date1.compareTo(date2); if (…...

el-table 指定层级展开

先来看看页面默认全部展开时页面的显示效果&#xff1a;所有节点被展开&#xff0c;一眼望去杂乱无章&#xff01; 那么如何实现只展开指定的节点呢&#xff1f;最终效果如下&#xff1a;一眼看去很舒爽。 干货上代码&#xff1a; <el-table border v-if"refreshTabl…...

3288S Android11 适配红外遥控功能(超详细)

目录 一、rk3288平台红外遥控介绍二、原理图分析三、配置设备树并使能红外遥控功能四、打开红外打印功能&#xff0c;查看红外遥控的用户码和键值五、将查看到的红外遥控用户码和键值添加到设备树和.kl文件六、Android红外遥控.kl文件映射知识和使用添加新的.kl文件七、补充&am…...

Linux高性能服务器编程 学习笔记 第三章 TCP协议详解

与IP协议相比&#xff0c;TCP协议更靠近应用层&#xff0c;因此在应用程序中有更强的可操作性。一些重要的socket选项都和TCP协议相关。 本章从以下方面讨论TCP协议&#xff1a; 1.TCP头部信息。TCP头部信息出现在每个TCP报文段中&#xff0c;用于指定通信的源端端口号、目的端…...

【云原生】Kubernetes学习笔记

部署 在部署前强调几点 不要使用IPv6, 很多组件都不支持IPv6不要使用最新版本, 最新版本非常不稳定, 甚至可能存在无法运行的bug不要版本更新, 安装后就将版本固定下来, 新的版本可能会引入新功能, 或移除旧功能, 导致Kubernetes无法运行 Kubeadm介绍 K8s是由多个模块构成的…...

[Machine Learning][Part 2]监督学习的实现

目录 线性模型实现&#xff1a; cost function &#xff1a;代价函数或者损失函数——衡量模型优劣的一个指标 理论&#xff1a; 代码实现: 梯度下降——自动寻找最小的cost function 代价函数 梯度的概念&#xff1a; 梯度下降公式&#xff1a; 实现一个简单的监督学习…...

【计算机毕业设计】基于SpringBoot+Vue大学生心理健康管理系统的开发与实现

博主主页&#xff1a;一季春秋博主简介&#xff1a;专注Java技术领域和毕业设计项目实战、Java、微信小程序、安卓等技术开发&#xff0c;远程调试部署、代码讲解、文档指导、ppt制作等技术指导。主要内容&#xff1a;毕业设计(Java项目、小程序等)、简历模板、学习资料、面试题…...

下载水果FLStudio21.2软件安装更新教程

编曲是一种对音乐创作过程中涉及的元素和步骤进行组织和安排的艺术形式。对于想要学习编曲的人来说&#xff0c;以下是一些有用的建议&#xff1a; 1. 学习基础知识 在开始学习编曲之前&#xff0c;你需要掌握一些基础知识&#xff0c;例如音乐理论、乐器演奏和数字音乐制作技…...

人工智能机器学习-飞桨神经网络与深度学习

飞桨神经网络与深度学习-机器学习 目录 飞桨神经网络与深度学习-机器学习 1.机器学习概述 2.机器学习实践五要素 2.1.数据 2.2.模型 2.3.学习准则 2.4.优化算法 2.5.评估标准 3.实现简单的线性回归模型 3.1.数据集构建 3.2.模型构建 3.3.损失函数 3.4.模型优化 3…...

linux部署页面内容

/bin&#xff1a;该目录包含了常用的二进制可执行文件&#xff0c;如ls、cp、mv、rm等等。 /boot&#xff1a;该目录包含了启动Linux系统所需的文件&#xff0c;如内核文件和引导加载程序。 /dev&#xff1a;该目录包含了所有设备文件&#xff0c;如硬盘、光驱、鼠标、键盘等等…...

若依框架集成WebSocket带用户信息认证

一、WebSocket 基础知识 我们平时前后台请求用的最多的就是 HTTP/1.1协议&#xff0c;它有一个缺陷&#xff0c; 通信只能由客户端发起&#xff0c;如果想要不断获取服务器信息就要不断轮询发出请求&#xff0c;那么如果我们需要服务器状态变化的时候能够主动通知客户端就需要用…...

0基础学习VR全景平台篇 第101篇:企业版功能-子账号分配管理

大家好&#xff0c;欢迎观看蛙色VR官方系列——后台使用课程&#xff01; 本期为大家带来蛙色VR平台&#xff0c;企业版教程-子账号分配管理功能&#xff01; 功能位置示意 一、本功能将用在哪里&#xff1f; 子账号分配管理功能&#xff0c;主要用于企业版用户为自己服务的终…...

adb 命令集

adb 查看app启动时间 1.清除时间 adb shell am start -S com.android.systemui/.SystemUIService2.启动应用并记录 adb shell am start -W <PACKAGE_NAME>/.<ACTIVITY_NAME>TotalTime: 491 adb 查看分辨率、dpi 分辨率 adb shell wm sizePhysical size: 1080…...

分享78个Python源代码总有一个是你想要的

分享78个Python源代码总有一个是你想要的 源码下载链接&#xff1a;https://pan.baidu.com/s/1ZhXDsVuYsZpOUQIUjHU2ww?pwd8888 提取码&#xff1a;8888 下面是文件的名字。 12个python项目源码 Apache Superset数据探查与可视化平台v2.0.1 API Star工具箱v0.7.2 Archery…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...