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的观点和思想,我要感谢他们对我的启发和帮助。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

三维模型3DTile格式轻量化压缩处理的数据质量提升方法分析

三维模型3DTile格式轻量化压缩处理的数据质量提升方法分析 在处理三维模型3DTile格式的轻量化压缩时,如何在减少数据量的同时,保证或提升数据质量是一大挑战。以下为一些提升数据质量的方法分析: 改进几何简化算法:在进行几何简化…

centos 7.9系统安装向日葵

1.下载地址 向日葵远程控制app官方下载 - 贝锐向日葵官网 2.下载依赖 yum install -y libappindicator-gtk3 安装好依赖之后,然后再安装向日葵软件 3.安装软件 sudo rpm -ivh 文件名.rpm 4.安装成功之后的位置

python脚本批量创建数据

背景 批量创建测试数据,利用python自带的库如faker库,节省大量的人工。准备工作 1、安装python,参考地址 https://www.runoob.com/python3/python3-install.html 2、设置环境变量(不同操作系统) PATH“$PATH:/usr/local/bin/python” 3、查…

力扣-217.存在重复元素

Method 1 先对整个数组进行排序&#xff0c;然后从前往后开始遍历&#xff0c;判断前一个数 是否跟相邻的数相等 AC Code class Solution { public:bool containsDuplicate(vector<int>& nums) {sort(nums.begin(),nums.end());int front nums[0];for( int i 1; i…

亚马逊云科技 Amazon Lightsail :一种在云服务器上运行容器的简单方法

当向开发人员介绍亚马逊云科技云服务时&#xff0c;通常会花一点时间来介绍并演示 Amazon Lightsail 。它是迄今为止开始使用亚马逊云科技的最简单方法。使用它&#xff0c;您在几分钟内即可在自己的虚拟服务器上运行您的应用程序。而后增加了在 Amazon Lightsail 上部署基于容…

商业综合体AI+视频安防监控与智能监管解决方案

一、方案背景 商业综合体需要具备更好的品质和环境才能吸引更多客流&#xff0c;如何有效地进行内部管理、外部引流&#xff0c;是综合体管理人员思考的重点。 传统的视频监控需要靠人盯牢屏幕或者发生报警后通过查看录像&#xff0c;才能找到意外事件相关人员与起因&#xf…

走心分享!天津诚筑说Java大数据培训我该如何选择?

随着互联网的发展&#xff0c;IT行业变得越来越炙手可热&#xff0c;其中较为火热的当属大数据和Java了&#xff0c;许多学员都很纠结&#xff0c;Java和大数据我应该如何选择呢?今天小编带大家了解一下Java和大数据之间的区别&#xff01; Java和大数据的关系 Java是一种面…

偶现来电时手机操作出现重启

问题描述&#xff1a;偶现来电时手机操作出现重启 问题分析&#xff1a;从系统Log看 09-06 10:22:44.791829 1400 1425 W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in handler on main thread (main) 09-06 10:22:44.794133 1400 1425 W Watchdog: main …

【2023华为杯B题】DFT类矩阵的整数分解逼近(思路及代码下载)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Golang代码漏洞扫描工具介绍——trivy

Golang代码漏洞扫描工具介绍——trivy Golang作为一款近年来最火热的服务端语言之一&#xff0c;深受广大程序员的喜爱&#xff0c;笔者最近也在用&#xff0c;特别是高并发的场景下&#xff0c;golang易用性的优势十分明显&#xff0c;但笔者这次想要介绍的并不是golang本身&a…

华为云云耀云服务器L实例评测|netdata的部署与应用

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 看这里 前言何为netdata安装 前言 前两天&#xff0c;给大家介绍了下关于使用华为云云耀云服务器L实例做了几个案例应用&#xff0c;分别为&#xff1a; 华为云云耀云服务器L实例评测|一个…

mysql集群使用nginx配置负载均衡

参考链接&#xff1a;https://mu-sl.com//archives/mysql%E9%9B%86%E7%BE%A4%E4%BD%BF%E7%94%A8nginx%E9%85%8D%E7%BD%AE%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1 配置文件nginx_tcp.conf 示例 load_module modules/ngx_stream_module.so;stream{upstream tcpssh{hash $remote_…

Intel酷睿和AMD锐龙

Intel酷睿系列&#xff0c;主要分i3、i5、i7、i9 如&#xff1a;Intel 酷睿i5 10210U i5&#xff1a;品牌修饰符。 10&#xff1a;代次指示符。 210&#xff1a;sku编号。 常见后缀&#xff1a; G1-G7&#xff1a;集显等级。 U&#xff1a;低功耗。 H&#xff1a;标压版…

Unity制作旋转光束

Unity制作旋转光束 大家好&#xff0c;我是阿赵。 这是一个在很多游戏里面可能都看到过的效果&#xff0c;在传送门、魔法阵、角色等脚底下往上散发出一束拉丝形状的光&#xff0c;然后在不停的旋转。 这次来在Unity引擎里面做一下这种效果。 一、准备材料 需要准备的素材很简…

14:00面试,14:06就出来了,问的问题过于变态了。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

2023-2024年最新大数据学习路线

文章目录 2023-2024年最新大数据学习路线大数据开发入门*01*阶段案例实战 大数据核心基础*02*阶段案例实战 千亿级数仓技术*03*阶段项目实战 PB级内存计算04阶段项目实战 亚秒级实时计算*05*阶段项目实战 大厂面试*06* 2023-2024年最新大数据学习路线 新路线图在Spark一章不再…

SpringBoot 员工管理---通用模板 ---苍穹外卖day2

感谢点击 希望你有所收获! 目录 1.新增员工 需求分析:根据页面原型进行业务分析 接口设计 数据库设计 代码开发 功能测试 如何在接口文档中统一添加JWT令牌 ​ 获取当前登录员工的ID 2.员工分页查询 需求分析 代码开发 如何将日期格式化 ​3.启用禁用员工 1.新…

Spring | 事件监听器应用与最佳实践

引言 在复杂的软件开发环境中&#xff0c;组件之间的通信和信息交流显得尤为重要。Spring框架&#xff0c;作为Java世界中最受欢迎的开发框架之一&#xff0c;提供了一种强大的事件监听器模型&#xff0c;使得组件间的通信变得更加灵活和解耦。本文主要探讨Spring事件监听器的…

设备巡检电力水利物业巡检小程序开源版开发

设备巡检电力水利物业巡检小程序开源版开发 以下是设备巡检电力水利物业巡检小程序开源版的可能功能列表&#xff1a; 用户登录/注册&#xff1a;用户可以通过手机号或其他方式进行登录和注册。 首页展示&#xff1a;展示设备巡检电力水利物业巡检小程序的基本信息和操作指南…

Linux内核源码分析 (B.2)深入理解 Linux 物理内存管理

Linux内核源码分析 (B.2)深入理解 Linux 物理内存管理 文章目录 Linux内核源码分析 (B.2)深入理解 Linux 物理内存管理[TOC] 1\. 前文回顾2\. 从 CPU 角度看物理内存模型2.1 FLATMEM 平坦内存模型2.2 DISCONTIGMEM 非连续内存模型2.3 SPARSEMEM 稀疏内存模型2.3.1 物理内存热插…