目录

 1. 指针变量为什么要有类型?

2. 野指针

2.1 未初始化导致的野指针

2.2 指针越界导致的野指针

2.3 如何规避野指针 

3. 指针运算

3.1 指针加减整数

3.2 指针减指针

3.3 指针的关系运算

4. 二级指针

5. 指针数组

5.1 如何使用指针数组模拟二维数组

        上一期已经解释了指针和指针变量的区别以及含义,这一期我们来具体了解一下指针到底有什么作用。

 1. 指针变量为什么要有类型?

        我们知道指针变量的大小是根据所在平台决定的,若平台是32位即x86环境,则指针变量是4个字节,若平台是64位,则指针变量是8个字节。既然指针变量不会根据指针类型变化,那么我们为什么要区分指针变量的类型呢?换句话说char* 和 int* 都有能力存储4个字节的地址,为什么不统一成一个自定义的指针变量例如ptr*

        从上图可以得知,我们把int*类型的地址强行赋给char*类型的地址,再进行取值调用的时候,会根据char*来进行赋值以至于只会将一个字节赋值成0,若是正常使用int*来接收,那么四个字节都是0 ,如下图所示。

        由下图可知,虽然不同指针变量的存储类型不影响地址的存储,但是当直接对地址进行运算,还是会根据指针类型的不同进行运算。char*类型+1,跳过1个字节,int*类型+1,跳过4个字节。

所以我们会得到这样的结论:指针变量的类型在存取地址的时候可有可无,在修改地址指向的内容的时候是非常有必要的,它决定了在利用地址更改值的时候需要更改多少个字节;若直接对地址进行运算,那么会根据指针变量的类型+‘1’,这个‘1’可能是char类型的一个字节,也可能是int类型的四个字节。 

使用float*和int*的时候,无论是访问内存还是使用内存,都是4个字节,那么可不可以混用呢?

答案是:不可以

下图是整型解引用赋值整型,我们可以看到100以16进制存入内存。

我们把100.0存入内存,发现内存存的数据发生了变化, 虽然都是100,但是浮点数存入内存的方式是不同的。

2. 野指针

        指针指向的内存没有初始化,或者已经被销毁,此时的指针称为野指针。

2.1 未初始化导致的野指针

2.2 指针越界导致的野指针

2.3 如何规避野指针 

①指针初始化。

②指针小心越界。

③指针指向的空间置为NULL。NULL是0,类型是void*,如果取值的话一定会报错(默认0地址不能访问),所以,我们可以先判断这个指针如果不是NULL再进行取值。

④避免返回局部变量的地址,因为局部变量已经被销毁了(没有那块内存空间的使用权限了)。

⑤指针使用之前检查有效性。

3. 指针运算

3.1 指针加减整数

这里的values[N_VALUES]并不算下标越界,因为并没有使用这段内存,只是用了一下这个地址作为判断条件。

3.2 指针减指针

当同类型的地址减去同类型的另外一个地址,得出的结果的绝对值是两个地址之间的元素个数

需要注意的是,两个指针指向的必须是同一块内存,不然毫无意义。

        那么有同学会想,指针+指针得到的结果是什么呢,这个结果毫无意义,类似于你可以把日期相减,得到天数,但是你不能把日期相加,这样就毫无意义

3.3 指针的关系运算

其实就是地址之间的比较,判断两个地址谁大谁小,从而对地址指向的内容进行操作。

4. 二级指针

        简单描述一下,就是指针变量里面存的地址,这个地址是一个指针的地址。乍一听是不是以为在说绕口令呢?下面用一张图来进行诠释。

        上图中表示int * pa = &a;我们可以这么理解:*号表明pa的类型是一个指针类型,int表明这个指针类型指向的是int类型;那么我们是不是可以来理解一下二级指针。

        int* *ppa = &pa;还是将类型拆开,距离ppa最近的*表明ppa是一个指针,int* 表明ppa指向的类型是int*的类型

总结:二级指针是用来存放一级指针变量的地址

5. 指针数组

主语是数组,即存放指针的数组就是指针数组

5.1 如何使用指针数组模拟二维数组

        首先构造出三个一维数组,所谓二维数组就是将这三个一维数组连起来;我们构造一个指针数组,分别存入之前构造的一维数组名,在之前的帖子说明,一维数组名是数组的第一个元素的地址,所以分别存入了三个地址,我们需要遍历指针数组,得到三个一维数组的首地址,再引入一个变量j,根据指针加减法,就可以访问一维数组中除了第一个元素的其他元素的地址,最后解引用就可以得到最后的结果。

#include <stdlib.h>int main()
{int arr1[4] = {1,2,3,4};int arr2[4] = {2,4,6,8};int arr3[4] = {3,6,9,12};
// 用一维数组模拟出二维数组的效果int* arr_sum[3] = {arr1,arr2,arr3};for(int i = 0;i < 3;i++){for(int j = 0;j < 4;j++){printf("%d ",*(arr_sum[i] + j));}printf("\n");}return(0);
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV 图形API(13)用于执行两个矩阵(或图像)逐元素乘法操作的函数mul()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 描述 计算两个矩阵的每个元素的缩放乘积。 mul函数计算两个矩阵的逐元素乘积&#xff1a; dst ( I ) saturate ( scale ⋅ src1 ( I ) ⋅ src2 ( I ) ) …

人工智能混合编程实践:C++调用封装好的DLL进行图像超分重建

人工智能混合编程实践:C++调用封装好的DLL进行图像超分重建 前言相关介绍C++简介ONNX简介ONNX Runtime 简介**核心特点**DLL 简介**核心特点****创建与使用****应用场景****优点与挑战**图像异常检测简介应用场景前提条件实验环境项目结构C++调用封装好的DLL进行图像超分重建C…

Linux内核之高效缓冲队列kfifo

一、先说FIFO 队列是常见的一种数据结构&#xff0c;简单看来就是一段数据缓存区&#xff0c;可以存储一定量的数据&#xff0c;先存进来的数据会被先取出&#xff0c;First In Fist Out&#xff0c;就是FIFO。 FIFO主要用于缓冲速度不匹配的通信。 例如生产者&#xff08;数…

【面试篇】Kafka

一、基础概念类 问题&#xff1a;请简述 Kafka 是什么&#xff0c;以及它的主要应用场景有哪些&#xff1f; 答案&#xff1a;Kafka 是一个分布式流处理平台&#xff0c;它以高吞吐量、可持久化、可水平扩展等特性而闻名。其主要应用场景包括&#xff1a; 日志收集&#xff1a…

解释回溯算法,如何应用回溯算法解决组合优化问题?

一、回溯算法核心原理 回溯算法本质是暴力穷举的优化版本&#xff0c;采用"试错剪枝"策略解决问题。其核心流程如下&#xff1a; ​路径构建&#xff1a;记录当前选择路径​选择列表&#xff1a;确定可用候选元素​终止条件&#xff1a;确定递归结束时机​剪枝优化…

Vue 学习随笔系列二十二 —— 表格高度自适应

表格高度自适应 文章目录 表格高度自适应1、方法一2、方法二 1、方法一 根据页面元素计算各自占比 <template><div class"main"><div class"query-form" ref"Query"><QueryFormref"QueryForm"query"query&q…

ubuntu22.04.5安装docker,解决安装出现的错误,解决Docker hello-world没打印出来

文章目录 前言一 安装失败解决1结合具体报错分析2 首先怀疑是VPN的问题3 直接百度报错信息4最终解决问题 二 验证Docker hello-world没打印出来总结 前言 先说一下前面的情况&#xff0c;使用的是公司的工作站&#xff0c;登录公司一个帐号使用的公司网络&#xff0c;使用网上…

idea插件(自用)

.ignore git排除文件插件&#xff1a;.ignore介绍 Grep console 自定义日志颜色&#xff1a;Grep console介绍 AceJump 光标快速定位&#xff1a;AceJump介绍 Key promoter 提示插件:Key promoter介绍 MetricsReloaded 分析代码复杂度的插件&#xff1a;MetricsReload…

让AI再次伟大-MCP-Client开发指南

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理、AI应用&#x1f525;如果感觉…

供应链管理:计算题 / 倒扣法

一、理解倒扣法 在供应链管理中&#xff0c;倒扣法是一种常用的成本计算方法&#xff0c;主要用于确定商品的成本和销售价格&#xff0c;以确保特定的毛利率。倒扣法的基本原理是在已知售价和期望毛利率的情况下&#xff0c;逆推计算出供货价或成本价。 二、倒扣法的计算公式…

skynet.start 的作用详细解析

目录 skynet.start 的作用详细解析1. 功能概述2. 基本用法3. 关键作用(1) 注册消息处理函数(2) 启动事件循环(3) 服务生命周期管理 4. 与其他函数的协作5. 未调用 skynet.start 的后果6. 高级场景&#xff1a;何时不需要 skynet.start7. 总结 skynet.start 的作用详细解析 在 …

基于yolo11的BGA图像目标检测

1.产生图像数据的分辨率 2.产生图像的大小 3.产生图像是黑白或是RGB彩色 灰度图像&#xff0c;达到识别要求&#xff0c;减少计算量 4.标注数据的精准程度 1.模型标注后&#xff0c;少量标注全部人工校验&#xff0c;大量数据抽检&#xff0c;部分人工检验 2.明确边界框贴合…

PADS 9.5【附破解文件+安装教程】中文激活版下载

第1步 将软件安装包下载到电脑本地&#xff0c;使用解压工具进行解压打开&#xff08;全程关闭杀毒软件以及防火墙&#xff0c;避免破解文件被删除&#xff09; 第2步 鼠标右键以管理员身份运行“PADS9.5_mib.exe” 第3步 加载片刻后&#xff0c;弹出如图界面&#xff0c;点击N…

电子电气架构 --- SOC设计流程及其集成开发环境

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 周末洗了一个澡&#xff0c;换了一身衣服&#xff0c;出了门却不知道去哪儿&#xff0c;不知道去找谁&am…

图扑 HT 电缆厂 3D 可视化管控系统深度解析

在当今数字化浪潮席卷制造业的大背景下&#xff0c;图扑软件&#xff08;Hightopo&#xff09;凭借其自主研发的强大技术&#xff0c;为电缆厂打造了一套先进的 3D 可视化管控系统。该系统基于 HT for Web 技术&#xff0c;为电缆厂的数字化转型提供了有力支撑。 HT 技术核心架…

【数据结构】邻接矩阵完全指南:原理、实现与稠密图优化技巧​

邻接矩阵 导读一、图的存储结构1.1 分类 二、邻接矩阵法2.1 邻接矩阵2.2 邻接矩阵存储网 三、邻接矩阵的存储结构四、算法评价4.1 时间复杂度4.2 空间复杂度 五、邻接矩阵的特点5.1 特点1解析5.2 特点2解析5.3 特点3解析5.4 特点4解析5.5 特点5解析5.6 特点6解析 结语 导读 大…

Docker Registry 清理镜像最佳实践

文章目录 registry-clean1. 简介2. 功能3. 安装 docker4. 配置 docker5. 配置域名解析6. 部署 registry7. Registry API 管理8. 批量清理镜像9. 其他10. 参考registry-clean 1. 简介 registry-clean 是一个强大而高效的解决方案,旨在简化您的 Docker 镜像仓库管理。通过 reg…

UART双向通信实现(序列机)

前言 UART&#xff08;通用异步收发传输器&#xff09;是一种串行通信协议&#xff0c;用于在电子设备之间进行数据传输。RS232是UART协议的一种常见实现标准&#xff0c;广泛应用于计算机和外围设备之间的通信。它定义了串行数据的传输格式和电气特性&#xff0c;以确…

机器学习算法分类全景解析:从理论到工业实践(2025新版)

一、机器学习核心定义与分类框架 1.1 机器学习核心范式 机器学习本质是通过经验E在特定任务T上提升性能P的算法系统&#xff08;Mitchell定义&#xff09;。其核心能力体现在&#xff1a; 数据驱动决策&#xff1a;通过数据自动发现模式&#xff0c;而非显式编程&#xff08…