C语言入门Day_24 函数与指针

news2024/10/6 10:15:46

目录

前言:

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.coloradmin.cn/o/1033895.html

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

相关文章

【C++心愿便利店】No.6---C++之拷贝构造函数

文章目录 一、拷贝构造函数的引入二、拷贝构造函数 👧个人主页:小沈YO. 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:C 心愿便利店 🔑本章内容:拷贝构造函数 记得 评…

python安全工具开发笔记(四)——python网络编程

一、C/S架构 什么是C/S架构 C : Client S : Server。客户机和服务器结构。 Server 唯一的目的就是等待Client 的请求,Client 连上 Server 发送必要的数据,然后等待Server端完成请求的反馈。 C/S网络编程 Server端进行设置,首先创建一个通信…

怎么选择AI伪原创工具-AI伪原创工具有哪些

在数字时代,创作和发布内容已经成为了一种不可或缺的活动。不论您是个人博主、企业家还是网站管理员,都会面临一个共同的挑战:如何在互联网上脱颖而出,吸引更多的读者和访客。而正是在这个背景下,AI伪原创工具逐渐崭露…

ReadPaper论文阅读工具

之前看文献一直用的EndNote嘛,但是突然发现了它的一个弊端,就是说每次没看完退出去之后,下次再接着看的时候它不能保留我上一次的位置信息,又要重头开始翻阅,这让我感到很烦躁哈哈。(当然也不知道是不是我哪…

6条优势,anzo capital昂首资本相信MT5替代MT4的原因

投资者都知道MT5是在MT4基础上升级换代的多资产平台,MT5于2010年6月首次发布。anzo capital昂首资本认为MT5将完全取代MT4,就像MT4取代之前版本一样,因为有以下6条优势: 一.市场深度(DOM)数据。在MT4中,DOM几乎没有用…

GoAccess实时分析Nginx日志

GoAccess 是一个基于终端的实时 Web 日志分析仪。用 C 语言编写,它是快速,互动的,并以优雅而直观的方式显示日志。它提供了各种 Web 日志文件的支持,包括 Apache,Nginx,Caddy,Amazon S3 和 Clou…

c++STL概述

目录 STL基本概念 STL六大组件 STL的优点 STL三大组件 容器 算法 迭代器 普通的迭代器访问vector容器元素 算法for_each实现循环 迭代器指向的元素类型是自定义数据类型 迭代器指向容器 常用容器 string容器 string的基本概念 string容器的操作 string的构造函…

Python函数绘图与高等代数互融实例(六): 条形图|直方图|饼状图

Python函数绘图与高等代数互融实例(一):正弦函数与余弦函数 Python函数绘图与高等代数互融实例(二):闪点函数 Python函数绘图与高等代数互融实例(三):设置X|Y轴|网格线 Python函数绘图与高等代数互融实例(四):设置X|Y轴参考线|参考区域 Python函数绘图与高等代数互融实例(五…

代码随想录刷题 Day 16

104.二叉树的最大深度 class Solution { public:int get_max(TreeNode* root) {if(root NULL) return 0;int left_depth get_max(root->left);int right_depth get_max(root->right);int depth max(left_depth, right_depth) 1;return depth;}int maxDepth(TreeNod…

Kafka的消息传递保证和一致性

前言 通过前面的文章,相信大家对Kafka有了一定的了解了,那接下来问题就来了,Kafka既然作为一个分布式的消息队列系统,那它会不会出现消息丢失或者重复消费的情况呢?今天咱们就来一探。 实现机制 Kafka采用了一系列机…

Node2Vec实战---《悲惨世界》人物图嵌入

1. pip各个包后导入 import networkx as nx # 图数据挖掘 import numpy as np # 数据分析 import random # 随机数# 数据可视化 import matplotlib.pyplot as plt %matplotlib inline plt.rcParams[font.sans-serif][SimHei] # 用来正常显示中文标签 plt.rcParams[axes.uni…

ArtifactResolveException

bug描述 Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration :app:debugCompileClasspath. 产生原因 一般可能是更换了新AndroidStudio导致的。依赖库未能成功…

关于Safari浏览器报错:Failed to load resource: 发生SSL错误,无法建立到该服务器的安全连接

报错信息: Failed to load resource: 发生SSL错误,无法建立到该服务器的安全连接 XMLHttpRequest cannot load https://xxxxxxx due to access control checks. 具体如图下: 原因是:页面上的http请求变了https请求 解决办法…

【校招VIP】产品思维创意之活动推广

考点介绍: 对于活动新手来说,策划出一个活动创意不是难事。但是如何把做活动考虑周详,理清运营活动的思路和流程,避免重复工作却是需要沉淀的。运营活动有一个很重要的思路方法,就是倒推。九维这次来和你们讲述倒推的思…

day31多线程01

1.实现多线程 1.1简单了解多线程【理解】 是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能。 1.2并发和并行【理解】 并行:在同一时刻,有多个指令在多个CPU上…

大模型时代,探人工智能发展的新动向

导语 | 今年以来大模型的热度居高不下,人工智能成为国内外各大厂商争相布局的新赛道。那么近期 AI 领域有哪些值得关注的新趋势,它又将为软件开发带来哪些影响呢?今天,我们特邀了微智云科技 CEO、腾讯云 TVP 张虎老师,…

HR人才测评,什么是领导力?如何测评人的领导能力?

什么是领导力? 领导力指的是带领和组织团队,充分利用各种条件和资源,为团队目标而努力。具有卓越领导力的人,即使是在困难的条件下,也能充分利用条件,激励成员,提高团队的效率,朝着…

数据备份文件生成--根据表名生成对应的sql语句文件

最近客户有个需求,希望在后台增加手动备份功能,将数据导出下载保存。 当然,此方法不适用于海量数据的备份,这只适用于少量数据的sql备份。 这是我生成的sql文件,以及sql文件里的insert语句,已亲测&#x…

Software Grand Exposure: SGX Cache Attacks Are Practical【WOOT‘17】

目录 摘要引言我们的目标和贡献贡献新颖的SGX缓存攻击技术非加密应用程序泄漏对策分析 背景Intel SGX缓存结构性能监视计数器 系统和威胁模型对手的能力进攻目标 攻击设计PrimeProbePrimeProbe for SGX挑战 作者:Ferdinand Brasser, Urs M ̈uller, Alexandra Dmitr…

2023 第十二届中国智能产业高峰论坛 - 文档大模型的未来展望

目录 前言文档图像分析识别与理解中的技术挑战 文档图像分析识别与理解的研究主题文档图像分析与预处理文档解析与识别版面分析与还原文档信息抽取与理解AI安全知识化&存储检索和管理 多模态大模型在文档图像处理中的应用多模态的GPT-4在文档图像上的表现多模态的Google Ba…