指针 (四)
一 . 指针的使用和传值调用
(1)strlen 的模拟实现
库函数 strlen 的功能是求字符串长度,统计的是字符串中 ' \0 ' 之前的字符个数,函数原格式如下:
我们的参数 str 接收到一个字符串的起始地址,然后开始统计字符串中 ' \0 ' 之前的字符个数,最终返回长度。现在我们来模拟实现 strlen 函数,只要从起始地址开始,向后逐个遍历字符,每遇到一个字符,判断其是否为 ' \0 ',若不是,则计数器 + 1,是则停止
(2)传值调用和传址调用
这两个的区别,我们可以通过一道题深入理解:
写一个函数,交换两个整型变量的值:
1 . 传值调用:
上图就是传值调用,看似没有问题,但我们的运行结果却出乎了我们的意料,a、b 的值并没有按照我们预想的那样交换,这是为什么呢?我们可以通过调试中的监视来观察观察:
在上方两个调试的图中,我们可以看到,在我们的 Swap1 中,的的确确是将我们的 x、y 的值进行了交换,但是我们也可以看到,a、b (实参)的地址和 x、y (形参)的地址是截然不同的,这就证明,a、b 和 x、y 有着本质上的区别,我们改变的是在 Swap1 中的 x、y ,并不是我们想要改变的 a、b(地址不同,证明 a、b 和 x、y 向内存申请的空间并不是同一块空间,这两者之间没有必要联系)
这里就引出一个重要概念:当实参传递给形参的时候,形参会单独创建一份临时空间来接收实参,对形参的修改不影响实参!!!
我们想要通过一个函数来达到交换变量值的目的,我们应该打破表象看本质,从变量的地址下手,用另一种方法——传址调用
1 . 传址调用:
如图,使用传址调用时,我们通过调试可以看到,a、b 和 *pa、*pb 的地址是一样的,通过地址去改变这两个变量的值,就可以从本质上去修改它俩的值
总结:传址调用,可以让函数和主调函数之间建立真正的联系,在函数内部可以修改主调函数中的变量;所以未来函数中只是需要主调函数中的变量值来实现计算,就可以采用传值调用;如果函数内部要修改主调函数中的变量的值,就需要传址调用
二 . 数组名的理解
之前我们提到过使用指针访问数组内容,我们知道了,数组名其本质就是首元素的地址,如下图:
这个时候就有小伙伴发出真挚的疑问了:讲道理,如果数组名就代表着首元素的地址,我们之前所见到的sizeof(arr)为什么是 40 而不是 4/8 呢?如下图:
这里呢就是我们的一个例外情况了哈,有关于数组名的使用有两个例外:(重点重点重点!!!)
(1)sizeof(数组名):当 sizeof ()中单独放置数组名,这里的数组名就表示整个数组,计算的是整个数组的字节大小
(2)& 数组名 :这里的数组名表示整个数组,取得是整个数组的地址(整个数组的地址与数组首元素的地址是有区别的)
三 . 指针访问数组
关键点的解读都在代码中为诸君做了注释,我就不过多赘述了
四 . 一维数组传参的本质
不知道大家有没有注意过,我们跟数组打了那么多次交道,sizeof()我们也用过多次,但我们一直都是在函数外部计算数组的元素个数,然后再通过传参的方式将 sz (元素个数)传递给函数。那么我们可不可以通过传参过来的数组直接在函数内部计算数组中的元素个数呢?不妨一试:
可以看到我们这个输出结果并不像我们预想的那样,问题就出在我们数组的传参上
在上面第二点我们提到过,数组名的本质是首元素地址。所以函数形参的部分理论上应该是使用指针变量来接收首元素的地址,那么在函数内部,我们这个时候使用 sizeof()计算的就不是一个数组的字节大小了,而是计算的一个地址的字节大小
不管我们怎么去传参,本质都是以指针形式表现的,如图:
总结:在函数内部我们使用sizeof()计算的都是对其首元素地址的字节大小(4 或 8由编译环境决定)。所以在函数内部是没法求数组的元素个数的
五 . 二级指针
众所周知,指针变量那也是变量,是变量就有地址,我们指针本身就是指向一个地址的,那么它本身作为一个变量而言,它的地址又存放在哪里呢?
这就是我们所谓的二级指针,这文字理解起来有点绕昂,跟俄罗斯套娃一样,咱们上图理解:
如图,这段代码的含义就是:
(1)创建了一个整型变量 a 并赋值为 10
(2)取出 a 的地址存放在指针(一级指针)pa 中
(3)同理再取出 pa 的地址存放在指针(二级指针)ppa 中
总结:二级指针的本质存放的就是一级指针的地址
文字、图片的表达能力终究有限,还望诸君见谅,自己细心一层一层地捋开指针之间的嵌套关系
六 . 指针数组
指针数组?到底是指针还是数组呢?一时半会捋不清的小伙伴们不妨类比一下我们学习过的知识:整型数组——存放整型的数组;字符数组——存放字符的数组
由此观之,指针数组就是用来存放指针的数组
指针数组当中的每一个元素都是一个指针,或者说每个元素都是指向内存中一块空间的地址
(1)指针数组模拟二维数组
不知道大家可还记得二维数组,我们可以先来回顾一下
想更仔细了解的,可以点链接查看我之前的博客哦,里面较为详细的介绍了二维数组的相关知识:二维数组 和 变长数组_变长二维数组-CSDN博客
接下来我们利用指针数组来模拟实现我们的二维数组:
前面提到过:指针数组就是用来存放指针的数组,我们这里三个数组——arr1、arr2、arr3,又新创建了一个 *parr ,而在这其中,将这三个数组放进去,又因为数组名就是首元素的地址,所以这里三个数组放到 parr 中时都是属于 int* 类型的指针,看下图更好理解:
应该注意的是:以上代码只是我们运用指针数组模拟实现的二维数组,并不是真正意义上的二维数组,因为它们的每一行并非连续的
这里没有什么生冷硬的知识,都是将我们学到过的知识点串联起来就可以得出,相信以诸君的聪明才智,定能轻松拿捏!
OKK,今天有关于指针的小部分知识就跟大家聊到这里,咱们下期再见咯。与诸君共勉!!!
相关文章:

指针 (四)
一 . 指针的使用和传值调用 (1)strlen 的模拟实现 库函数 strlen 的功能是求字符串长度,统计的是字符串中 \0 之前的字符个数,函数原格式如下: 我们的参数 str 接收到一个字符串的起始地址,然后开始统计…...

便利店(超市)管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图详细视频演示技术栈系统测试为什么选择我官方认证玩家,服务很多代码文档,百分百好评,战绩可查!!入职于互联网大厂,可以交流,共同进步。有保障的售后 代码参考数据库参…...

Excel中的“块”操作
在Excel中,有offset、index、indirect三个对“区域”操作的函数,是较高版本Excel中“块”操作的利器。 (笔记模板由python脚本于2024年08月20日 19:25:21创建,本篇笔记适合喜欢用Excel处理数据的coder翻阅) 【学习的细节是欢悦的历程】 Pytho…...

yolo V8训练 长条状目标
1、说明 目标数据集合中有很多长条状图片,如果直接Resize 会严重拉伸,因此采用把长条图像裁剪成2段,然后将裁剪后的2段图片拼接在一起。 2、代码 2.1 C 代码 (部署,模型推理时C ) #include <stdio.h…...

数据结构与算法 - 设计
1. LRU缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值࿰…...
62 网络设备的暗藏的操控者SNMP
一 SNMP 简介 SNMP(Simple Network Management Protocol,简单网络管理协议)广泛用于网络设备的远程管理和操作。SNMP允许管理员通过NMS对网络上不同厂商、不同物理特性、采用不同互联技术的设备进行管理,包括状态监控、数据采集和故障处理。 二 SNMP 网络架构 NMS(Netwo…...

华硕飞行堡垒键盘全部失灵【除电源键】
华硕飞行堡垒FX53VD键盘全部失灵【除电源键】 前言一、故障排查二、发现问题三、使用方法总结 前言 版本型号: 型号 ASUS FX53VD(华硕-飞行堡垒) 板号:GL553VD 故障情况描述: 键盘无法使用,键盘除开机键外…...
前端字符串将其分割成长度为 32 的子字符串数组
技巧分享:将字符串切割后,对list数据进行数据处理 要实现这个需求,可以编写一个简单的 JavaScript 函数来处理字符串并将其分割成长度为 32 的子字符串数组。下面是一个具体的实现示例: function splitStringIntoChunks(str) {l…...

小学二年级数学精选试题
小学二年级数学精选试题...
练习题 - 探索正则表达式re功能
在编程的世界里,正则表达式(Regular Expression, 简称re)是一种强大的工具,它能帮助我们有效地处理文本数据。从简单的查找到复杂的字符串操作,正则表达式都能轻松应对。特别是在数据清理、文本分析以及自动化处理等场景中,正则表达式更是不可或缺的利器。本篇文章将深入…...

【Oracle 11G 配置使用教程1】
Oracle11G配置使用教程1 引言图像方式创建数据库一、打开 Database Configuration Assistant二、创建数据库操作三、选择数据库模版四、配置数据库标识五、配置数据库标识六、创建数据库 配置监听一、打开创建监听程序二、打开创建监听程序三、重新配置监听程序四、选择监听程序…...
【ubuntu24.04】docker pull 配置
Docker 镜像加速器 的方式,看起来不行。阿里云的要先登录。手动拉取tar包的方式,官方dockerhub看起来本身没提供。docker pull 的 代理与 环境变量的代理不同因此,docker pull gitlab/gitlab-ce:17.3.0-ce.0 使用了全局代理也会失败参考官方文档: Use a proxy server with …...

《机器学习》—— 通过下采样方法实现银行贷款分类问题
文章目录 一、什么是下采样方法?二、通过下采样方法实现银行贷款分类问题三、下采样的优缺点 一、什么是下采样方法? 机器学习中的下采样(Undersampling)方法是一种处理不平衡数据集的有效手段,特别是在数据集中某些类…...

Synchronized重量级锁原理和实战(五)
在JVM中,每个对象都关联这一个监视器,这里的对象包含可Object实例和Class实例.监视器是一个同步工具,相当于一个凭证,拿到这个凭证就可以进入临界区执行操作,没有拿到凭证就只能阻塞等待.重量级锁通过监视器的方式保证了任何时间内只允许一个线程通过监视器保护的临界区代码. …...

linux常用网络工具汇总三
linux常用网络工具汇总 6. 抓包工具6.1 wireshark安装界面介绍使用过滤器TCP协议示例关于wireshark的缺点 6.2 tcpdump命令格式关键字使用关于tcpdump的缺点 6.3 fiddler6.4 burpsuite 6. 抓包工具 6.1 wireshark Wireshark(前称Ethereal)是一个网络封…...
Linux中nano编辑器详解
nano 是一个简单的文本编辑器,通常预装在大多数 Linux 发行版中。它非常适合初学者使用,因为它有一个用户友好的界面和易于理解的命令集。下面是对 nano 编辑器的详细说明。 启动 nano 要启动 nano 并打开一个文件进行编辑,你可以在终端中输…...
26-vector arraylist和linkedlist的区别
Vector, ArrayList, 和 LinkedList 是Java中常见的三种列表实现,它们各自具有不同的特点和适用场景。 同步性与线程安全: Vector 是同步的,即线程安全的,它的所有方法都是同步的,可以由两个线程安全地访问…...
20-redis穿透击穿雪崩
Redis中的缓存穿透、缓存击穿和缓存雪崩是三种常见的缓存问题: 缓存穿透:指缓存和数据库中都没有的数据,但用户还是源源不断地发起请求,导致每次请求都会直接访问数据库,从而可能压垮数据库。缓存击穿&…...

Docker使用教程
Docker 名词解释 镜像(image):Docker镜像就是一个模板,可以通过这个模板来创建容器服务。容器(container):Docker利用容器技术,独立运行一个或者一组应用,通过镜像创建…...
poi-tl循环放图片+文字说明
这几天有个任务,服务端导出word要求从数据库取到多张图片,然后输出到word中,并且说明一共几张,当前是第几张。 网上翻了很久也没有找到示例,不过最终难题还是得到了攻克。 因为之前的代码是有一个导出的map,…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...