指针 (四)
一 . 指针的使用和传值调用
(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,…...

数据结构之树的存储结构
一、顺序存储结构 顺序存储结构通常用于表示完全二叉树。在这种存储方式中,树中的节点被存储在一个连续的数组中。对于完全二叉树,如果父节点的索引是i(假设从0开始计数),那么它的左子节点的索引是2i1,右子…...

Zotero 常用插件介绍
1. Zotero 插件安装方法 下载以 .xpi 结尾的插件;打开 Zotero → 工具 → 插件 → 右上小齿轮图标 → Install Add-on From File ... → 选择下载好的 .xpi 插件安装 → 重启 Zotero 2. 常用插件介绍 2.1. Scholaread - 靠岸学术 Zotero 英文文献相关插件…...

WebSocket协议解析
文章目录 一、HTTP协议与HTTPS协议1.HTTP协议的用处2.HTTP协议的特点3.HTTP协议的工作流程4.HTTPS协议的用处5.HTTPS协议的特点6.HTTPS协议的工作流程 二、WebSocket协议出现的原因1. 传统的HTTP请求-响应模型2. 轮询(Polling)3. 长轮询(Long…...

ES6 (一)——ES6 简介及环境搭建
目录 简介 环境搭建 可以在 Node.js 环境中运行 ES6 webpack 入口 (entry) loader 插件 (plugins) 利用 webpack 搭建应用 gulp 如何使用? 简介 ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版…...

HarmonyOS开发案例:列表场景实例-TaskPool
介绍 本实例通过列表场景实例讲解,介绍在TaskPool线程中操作关系型数据库的方法,涵盖单条插入、批量插入、删除和查询操作。 效果图预览 使用说明 进入页面有insert(单条数据插入)、batch insert(批量数据插入)、query(查询操作)三个按钮,…...

谷歌浏览器如何隐藏书签
谷歌浏览器的书签栏是一个极为方便的功能,它能够帮助用户快速访问自己频繁使用的网页。然而,有些时候为了保护个人隐私或使浏览界面更为简洁,我们可能需要隐藏书签栏。接下来就为大家分享如何隐藏谷歌浏览器的书签栏,一起来看看吧…...

SQL - 视图
我们可以把查询或子查询存到视图里,视图的作用就像一张虚拟表,再次查询时,就不需要再写一次复杂的查询。创建视图 create view 视图名 as (查询); create or replace view clients_balance as (查询); create or replace view clients_balanc…...

centos7环境升级默认的gcc 4.8.5到gcc 8.2.0, 并且升级glibc到glibc 2.28
这里写目录标题 makegccglibc make #下载 wget http://ftp.gnu.org/gnu/make/make-4.2.tar.gz tar -xf make-4.2.tar.gz cd make-4.2 ./configure make -j4 make install mv /usr/bin/make /usr/bin/make_bak cp ./make /usr/bin/make -v GNU Make 4.2 Built for x86_64-pc-li…...

FastHTML:使用 Python 彻底改变 Web 开发
什么是 FastHTML?🌐 FastHTML 是一个现代 Python Web 应用程序框架,其真正目的是让 Python 开发人员轻松进行 Web 开发。它大大减少了对 JavaScript 和 CSS 构建交互式和可扩展 Web 应用程序的依赖。FastHTML 通过使用 Python 对象来表示 HTM…...

快速排序的深入优化探讨
快排性能的关键点分析 决定快排性能的关键点是每次单趟排序后,key对数组的分割,如果每次选key基本⼆分居中,那么快排的递归树就是颗均匀的满⼆叉树,性能最佳。但是实践中虽然不可能每次都是⼆分居中,但是性能也还是可…...