C语言(指针)5

                Hi~!这里是奋斗的小羊,很荣幸各位能阅读我的文章,诚请评论指点,关注+收藏,欢迎欢迎~~     

                                💥个人主页:小羊在奋斗

                                💥所属专栏:C语言   

        本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为同样是初学者的学友展示一些我的学习过程及心得。文笔、排版拙劣,望见谅。

                                7、指针数组模拟二维数组

                                8、字符指针

                                9、数组指针

                                                9.1数组指针的创建

                                                9.2数组指针指针指针数组

                                10、二维数组传参的本质

7.指针数组来模拟二维数组

        用指针数组来表示二维数组是非常适合的,因为二维数组的每一行就像一个一维数组,这个一维数组也是可以通过指针来访问。 

        上面虽然我们没有定义二维数组,但我们用指针数组的方法模拟实现了二维数组。

        上面代码的执行细节是,我们首先对指针数组arr解引用找到对应下标的元素,其中元素也是地址,那我们再对这个地址解引用就能得到对应下标的元素,此时的元素就是arr1、arr2、arr3三个数组中存的整型元素。 

8、字符指针

        类似于整型指针,字符指针我们并不会感到陌生,因为用法跟整型指针很像:

        下面介绍一个不一样的用法:

        上面的两个指针变量pa和pc有什么区别呢?

        对于pa,我们先定义了一个字符数组,然后将字符串 “abcde” 存到数组中,再将数组首元素的地址存到了pa中,其中数组是可以被修改的

        那pc跟pa的区别在哪里呢?我们是将字符串 “abcde” 存到pc中吗?不是的,这个字符串 “abcde” 是一个常量字符串,而常量字符串作为一个表达式的时候,其值是首字符的地址,也就是说,我们是将首字符 ‘a’ 的地址存到了pc中。作为一个常量字符串,因为具有常属性,所以是不能被修改的。 

        来证实一下上面所说的内容:

        可以看到pc中存的确实是常量字符串 “abcde” 的首字符 ‘a’ 的地址。

        当我们尝试用字符 ‘w’ 替换字符 ‘a’ ,调试执行到这句代码的时候就报错,提示访问权限冲突,所以常量字符串确实是不能被修改的。但是在我们写下修改的这句代码后编译器并不会报错提示,只有当我们调试的时候才会报错提示,那有没有什么方法让我们写下这句代码后就提示错误的信息呢?这样我们就立马会知道我们写了错误的代码。

        提到不能被修改,还要提示报错得信息,相信你肯定已经想到了之前的文章中介绍过的const。它的作用不就是使一个值不能被修改,而且当你尝试修改的时候立马就会有错误提示信息。那我们就用const修饰指针变量pc,但是记得要放在 “ * ” 的左边。

        虽然pc内存的只是常量字符串 “abcde” 首字符 ‘a’ 的地址,但是我们想把整个字符串打印出来也是可以的。占位符用 %s,而使用 %s 打印字符串的时候,只需要提供首字符的地址就行

         了解了上面的内容,来看一个很典型的例题:

        请结合上面所讲的内容,仔细思考一下上面代码执行的结果是什么?提示一下,我们上面所说的 “常量字符串不能被修改” 这句话很关键。实在想不到也没有关系,我们先来看结果:

        可以看到,str1和str2是不一样的,而str3和str4是一样的。跟你想的结果一样吗?如果不一样,请耐心听我解释。

        我们定义了两个字符数组,并且同样用字符串 “abcde” 初始化,虽然这两个数组内存的内容是一样的,但两个数组不一样,也就是在内存中开辟的空间不一样,那str1和str2就不一样,因为数组就表示数组首元素的地址。

        还定义了两个字符指针,并同样将常量字符串 “abcde” 首字符 ‘a’ 的地址存到str3和str4中。我们说过常量字符串不能被改变,既然不能被改变那还有必要在内存中存两份或多份吗?答案是不需要的。既然内存中只存了一份常量字符串 “abcde”,那它首字符 ‘a’ 的地址就只有一个,所以str3和str4得到的地址是一样的,这里str3和str4指向的是同一个常量字符串。

        值得一说的是,str1、str2、str3、str4比较的都是地址,而不是其中存的值。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,它们实际会指向同一块内存。 

9、数组指针

        9.1数组指针的创建

        前面说了指针数组,这里再来了解一下数组指针。不用多说数组指针肯定是指针,不过这个指针指向的是数组,也就是说这个指针内存的是数组的地址。注意是数组的地址(&arr)而不是数组首元素的地址(arr / &arr[0])。

        数组指针该如何创建呢?跟其他类型的指针一样,创建之前应该先确定数组指针的类型吧。我们知道指针的类型取决于它所指对象的类型,比如整型指针指向的是整型所以整型指针的类型为 :int *,字符指针指向的是字符所以字符指针的类型为: char *,那同样的数组指针指向的是数组所以数组指针的类型就应该为:数组类型 *。数组类型我们之前说过,去掉数组名剩下的就是数组类型。

        比如定义一个整型数组:int arr[10],那么创建一个数组指针将数组arr的地址存到数组指针中就应该是:int *arr[10],但是这不就成了指针数组了吗?所以我们还需要简单调整一下,将数组名和代表指针的 “ * ” 用括号括起来,使它们两个结合,就得到了正确的数组指针的写法:int (*arr)[10],数组指针类型就是:int (*)[10]。

        那通过数组指针怎么得到这个数组内的元素呢?

        因为pa内存着数组的地址,所以我们得通过解引用指针变量pa来找到数组,找到这个数组就相当于拿到了数组名,那我们知道数组名也是地址(其实数组名也是一个指针类型),所以再解引用就拿到了数组内的元素。 

        9.2数组指针指向指针数组 

         说到这里又有一个问题需要我们思考,数组指针是存放数组地址的指针,那指针数组也是数组啊,将指针数组的地址存到数组指针内该如何存呢?解决这个问题前我们先来剖解一下数组指针各部分分别表示什么含义。

        了解清楚了数组指针各部分分别表示的含义,再来思考上面的问题。我们需要指针pa内存数组arr的地址,而这个数组内元素的类型是指针类型,假如这个指针指向的对象类型是int,那么,数组指针内存指针数组的地址的写法就应该是下面这样:

10、二维数组传参的本质

        我们之前在扫雷游戏中已经用过多次二维数组,这里再来回忆一下二维数组的用法:

        前面的文章中说,一维数组的数组名就是数组首元素的地址,一维数组传参的本质其实传递的就是数组首元素的地址,形参可以写成数组的形式也可以写成指针的形式。那二维数组呢?其实二维数组的数组名也是表示数组首元素的地址,二维数组传参的本质其实也传递的是数组首元素的地址,形参可以写成数组的形式也可以写成指针的形式。

        那问题来了,二维数组的首元素是什么呢?还记不记得我们在之前的文章中说过一句话:二维数组可以看做一维数组的数组。也就是说我们把二维数组的一行看作了一个一维数组,这个一维数组也是有数组名的,数组名就是 “arr[0]”。既然如此那二维数组的首元素就是二维数组的第一行,也就是这个第一行是二维数组内的第一个 “一维数组”。

        上面我们打印二维数组的时候形参写的是数组的形式,那指针的形式怎么写呢?写指针的形式先要弄清楚这个指针的类型,指针的类型取决于指针指向对象的类型。二维数组传参传递的是二维数组第一行的地址,我们把一行又看作一个一维数组,所以这个指针指向的就是这个一维数组,那要存一个数组的地址,这个指针就应该是数组指针,可以理解为二维数组传参的时候降维成了数组指针。

        不管是一维数组还是二维数组传参,形参的部分可以写成指针的形式,也可以写成数组的形式,写成数组的方式更容易理解,但我们要知道本质还是指针。 

             如果觉得我的文章还不错,请点赞、收藏 + 关注支持一下,我会持续更新更好的文章。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Busybox 在 Docker 中的部署和启动

可以使用 docker pull 指令下载 busybox:latest 镜像: PS C:\Users\yhu> docker pull busybox:latest latest: Pulling from library/busybox ec562eabd705: Pull complete Digest: sha256:5eef5ed34e1e1ff0a4ae850395cbf665c4de6b4b83a32a0bc7bcb998e24e7bbb St…

COX回归特征筛选

任务:利用cox筛选出P值小于0.05的特征 数据的格式第一列为标签,第二列为时间,第三列及后为特征 先想一想,想好了再更新 这里我们先举一个例子: import pandas as pd from lifelines import CoxPHFitter# 创建示例数…

项目管理-计算题公式【复习】

1.【进度】相关公式 1.1三点估算 PERT 三点估算法是基于 任务成本的三种估算值(最可能成本CM,最乐观成本CO,最悲观成本CP)来计算预期成本的方法。 三角 分布:预期成本(最乐观成本最可能成本最悲观成本&am…

RabbitMq出现Not management user问题解决

在RabbitMq登录的时候突然弹出如下图: 提示“当前用户不是管理员用户”进入mq控制命令台下: windows版本在mq安装路径下的sbin下进入cmd弹出框; Linux版本没有测试; 输入以下命令: rabbitmqctl list_users 查询当…

【计算机网络篇】数据链路层(8)共享式以太网的退避算法和信道利用率

文章目录 🛸共享式以太网的退避算法🥚截断二进制指数算法 🍔共享式以太网的信道利用率 🛸共享式以太网的退避算法 在使用CSMA/CD协议的共享总线以太网中,正在发送帧的站点一边发送帧一边检测碰撞,当检测到…

Springboot整合 Spring Cloud Alibaba Sentinel

1.Sentinel介绍 官方文档地址: https://sentinelguard.io/zh-cn/docs/introduction.html https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入…

探索共享内存:解锁并发编程的潜力

文章目录 序言shm 原理对shm的理解通过代码认识shm调用shmget方法实现 序言 system V版本 指定的一种规则(俗话说一流公司定规则,二流公司重服务,三流公司重技术).这个规则虽然有很多种(消息队列,共享内存等只是比较出名的几个).但是在内核的相关技术解决上是类似的,因为都是基…

吴恩达 深度学习 神经网络 softmax adam 交叉验证

神经网络中的层:输入层(layer 0)、隐藏层、卷积层(看情况用这个)、输出层。(参考文章) 激活函数: 隐藏层一般用relu函数; 输出层根据需要,二分类用sigmoid&…

Selenium 自动化 —— 一篇文章彻底搞懂XPath

更多关于Selenium的知识请访问“兰亭序咖啡”的专栏:专栏《Selenium 从入门到精通》 文章目录 前言 一、什么是xpath? 二、XPath 节点 三. 节点的关系 1. 父(Parent) 2. 子(Children) 3. 同胞(S…

[Algorithm][回溯][全排列][子集] + 回溯原理 详细讲解

目录 0.原理讲解1.全排列1.题目链接2.算法原理详解3.代码实现 2.子集1.题目链接2.算法原理详解3.代码实现 0.原理讲解 回溯算法通常⽤于解决组合问题、排列问题和搜索问题等回溯算法的基本思想: 从⼀个初始状态开始,按照⼀定的规则向前搜索,…

怎么下载抖音直播视频 怎么解析直播间链接的视频录制保存

尊敬的读者们,你们好!今天我们将探讨一个非常实用的技巧——如何下载直播视频。随着网络技术的发展,直播视频已经成为我们日常生活中不可或缺的一部分。无论是观看比赛、欣赏音乐会还是探索新的美食,直播视频都为我们提供了更直观…

【qt】最快的开发界面效率——混合编程

混合编程 一.准备工作1.创建项目2.添加项目资源 二.ui界面设计1.menuBar菜单栏2.action ▲3.toolBar工具栏4.中心组件 三.代码界面设计1.toolBar添加组件2.statusBar状态栏添加组件 四.完成界面的功能1.对action配置信号槽2.对action转到信号槽3.代码添加的组件手动关联槽函数 …

YOLOv8+CLIP实现图文特征匹配

本文通过结合YOLOv8s的高效物体检测能力与CLIP的先进图像-文本匹配技术,展示了深度学习在处理和分析复杂多模态数据中的潜力。这种技术的应用不仅限于学术研究,还能广泛应用于工业、商业和日常技术产品中,以实现更智能的人机交互和信息处理。…

第四届微调——炼丹

学习地址:Tutorial/xtuner/README.md at main InternLM/Tutorial GitHub 笔记 微调是一种在已有的预训练模型基础上,通过使用新的数据对模型进行进一步优化和调整的技术手段。它的目的是使模型能够更好地适应特定的应用场景和任务需求,进一…

IDEA切换分支

方法一 1、选择要切换分支的module 2、右键,选择git 3、再点击branches 4、可以看到当前module的本地分支(local Branches)及远程分支(Remote Branches)列表。点击你要切换到的分支,Checkout即可。 方法二 1、点击…

MFC编程之设计美丽的对话框

目录 写在前面: Part 1:美美的设计一下计算器的布局 1.描述文字: ​编辑 2.ID: Part 2:美美熟悉一下计算器的工作流程 Part 3:美美设计一下控件功能 1.edit control: 2.相关变量初始化&…

Copilot for Microsoft 365 扩充新增 16 种语言

最近,微软公司发布公告,进一步扩大 Copilot for Microsoft 365 语言支持,新增 16 种,支持的语言总数达到 25 种。 新支持的语言如下: 阿拉伯语 捷克语 丹麦语 荷兰语 芬兰语 希伯来语 匈牙利语 韩语 挪威语&am…

Java面试之分布式篇

分布式锁的实现方案 (1)用数据库实现分布式锁比较简单,就是创建一张锁表,数据库对字段作唯一性约束。加锁的时候,在锁表中增加一条记录即可;释放锁的时候删除锁记录就行。如果有并发请求同时提交到数据库&…

二分判定+选插冒排序+归并快速堆希尔+计数排序

二分力扣题 一&#xff1a;搜索二维矩阵 74. 搜索二维矩阵 按照题意&#xff1a;直接利用二维数组转换成一维数组进行求解 方法一&#xff1a;普通等于的二分查找 class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {t…

Shell编程之循环语甸与函数

for 遍历循环 1&#xff09;for 变量 in 取值列表 for i in $(seq 1 10) do 命令序列 .... done 2&#xff09;for ((变量初始值; 变量范围; 变量的迭代方式)) for ((i1; i<10; i)) do 命令序列 .... done IFS for循环取值列表分隔符 set | grep IFS …