深入理解 C/C++ 指针

深入理解 C++ 指针:指针、解引用与指针变量的详细解析

在这里插入图片描述

前言

在 C++ 编程语言中,指针 是一个非常强大且重要的概念。对于初学者来说,指针往往会让人感到困惑不解。本文将通过形象的比喻,帮助大家深入理解指针、解引用与指针变量的概念,带你一步步掌握指针的使用。

什么是指针?

简单来说,指针 是一个保存了内存地址的变量。普通变量存储的是数据本身,而指针存储的是某个变量的内存地址。可以通过指针访问到该内存地址中存储的数据。

形象比喻:

想象一下,你有一个朋友要去你家找你:

  • 你家的地址:就像指针,它不是你本人,但指向了你家,告诉别人如何找到你。
  • 你本人:就是存储在内存中的实际数据,当有人通过你家的地址找到你时,就等于通过指针访问到了内存中的实际数据。

代码示例:

int a = 5;       // 变量 a 存储的是数值 5
int *p = &a;     // 指针 p 保存了变量 a 的地址

在这个例子中,a 是一个普通变量,存储了值 5,而 p 是一个指针,它保存了变量 a 的内存地址。也就是说,p 知道 a 存储在内存的什么位置。

解引用是什么?

当我们知道了变量的地址后,如何通过这个地址去访问实际存储的数据呢?这就需要用到解引用

解引用 是指通过指针访问指针所指向的内存中的数据。解引用操作符是星号(*)。当你对指针使用 * 操作时,表示你要访问指针指向的那个变量的值。

形象比喻:

  • 通过朋友知道了你家的地址,但要真正找到你,需要按照这个地址走到你家门口,敲门,看到你本人。这就是解引用的过程。

代码示例:

int a = 5;       // 变量 a 存储的是数值 5
int *p = &a;     // 指针 p 保存了变量 a 的地址cout << *p;      // 输出 a 的值,通过解引用访问 a

在上面的例子中,*p 代表通过指针 p 访问 a 的值,所以 cout 将会输出 5

总结:

  • p 保存的是 a 的地址(指针)。
  • *p 解引用 p,表示我们访问了 a 的值(实际数据)。

指针与普通变量的区别

类型描述类比
普通变量存储的是数据本身家里的物品
指针存储的是某个变量的内存地址你家的地址
指针解引用通过指针找到并访问该地址存储的值朋友找到你本人

普通变量可以直接操作存储的数据,而指针存储的是地址,你需要通过解引用操作符 * 来访问指针所指向的数据。

代码示例一:交换两个整数的最大最小值

示例一代码:

#include<iostream>
using namespace std;int main() {int *p1, *p2, *p, a, b; cout << "请输入两个整数" << endl;cin >> a >> b;  // 输入两个整数p1 = &a;       // p1 指向 ap2 = &b;       // p2 指向 bif (a < b) {   // 交换 p1 和 p2 的指向,使得 p1 始终指向较大的值p = p1;   p1 = p2;p2 = p;}cout << "a=" << a << "b=" << b << endl;cout << "max=" << *p1 << " min=" << *p2 << endl; // 输出最大值和最小值return 0;
}

示例一结果:

请输入两个整数
45 78
a=45 b=78
max=78 min=45
示例一解释:
  • 在这个例子中,我们通过 p1p2 这两个指针分别指向变量 ab。程序判断 a 是否小于 b,如果是,则交换 p1p2 的指向。最终,p1 始终指向较大的值,p2 指向较小的值。通过解引用 *p1*p2,我们分别得到了 ab 的最大值和最小值。

  • 关键点:这个示例展示了如何使用指针交换两个变量的指向,而不需要实际交换变量 ab 的值。

代码示例二:交换两个整数的值

示例二代码:

#include<iostream>
using namespace std;int main() {int *p1, *p2, a, b; cout << "请输入两个整数" << endl;cin >> a >> b;  // 输入两个整数p1 = &a;       // p1 指向 ap2 = &b;       // p2 指向 bif (a < b) {   int p;p = *p1;   // 将 p1 指向的值赋给临时变量 p*p1 = *p2; // 将 p2 指向的值赋给 p1 所指向的地址(a)*p2 = p;   // 将临时变量 p 的值赋给 p2 所指向的地址(b)}cout << "a=" << a << "b=" << b << endl;cout << "max=" << *p1 << " min=" << *p2 << endl; // 输出最大值和最小值return 0;
}

示例二结果:

请输入两个整数
45 78
a=78 b=45
max=78 min=45
示例二解释:
  • 在这个例子中,我们不仅仅交换了指针指向的地址,还交换了 ab 这两个变量的值。首先,通过 p1p2 分别指向 ab。然后,使用一个临时变量 p 存储 p1 所指向的值(即 a 的值),接着将 p2 所指向的值赋给 p1,再将临时变量 p 的值赋给 p2。最终实现了 ab 的值交换。

  • 关键点:此示例展示了如何通过解引用指针来实际交换两个变量的值。

指针与解引用的区别和联系

通过上述两个例子可以看出:

  1. 示例一中,我们交换的是指针的指向,也就是说 p1p2 交换后,指向不同的变量,但 ab 的值并没有改变。

  2. 示例二中,我们实际交换了指针指向的变量的值,通过解引用 *p1*p2,将 ab 的值进行了交换。

两者的核心区别在于,示例一中的指针仅仅是交换了指向的对象,而示例二通过解引用操作符 * 实现了对象本身值的交换。
在这里插入图片描述

常见错误

初学者在使用指针时容易犯一些常见错误,下面是两个需要特别注意的地方:

  1. 未初始化指针:在给指针赋值之前,指针变量是未初始化的,它可能指向一个随机的内存地址,这可能会导致程序崩溃。

    int *p;       // 没有初始化
    cout << *p;   // 错误!未初始化的指针解引用
    

    解决方法:指针在使用之前一定要初始化。比如可以让指针指向某个已知变量,或者将其初始化为 nullptr

    int *p = nullptr;   // 指针初始化为 nullptr
    
  2. 野指针:当指针指向的内存已经

被释放或无效时,指针就变成了“野指针”,对这种指针的操作会导致不可预期的结果,甚至崩溃。
cpp int *p = new int(10); // 动态分配内存 delete p; // 释放内存 cout << *p; // 错误!访问已经释放的内存

结束语

指针是 C++ 中非常强大的工具,能够让你直接操作内存,从而实现更灵活和高效的代码。但同时,指针的使用也伴随着一定的风险和复杂性。理解指针、指针变量和解引用是迈向高级编程的关键一步,希望本文的讲解和比喻能帮助你更好地掌握这一概念。

欢迎在评论区讨论你对指针的疑惑和心得!


这篇博客通过形象的比喻和代码示例,帮助读者更好地理解指针和解引用的概念。如果你觉得这篇博客对你有帮助,不妨分享给更多的朋友!在这里插入图片描述

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

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

相关文章

ELK:Elasticsearch、Logstash、Kibana Spring Cloud Sleuth和Spring Cloud Zipkin

〇、虚拟机中docker安装elasticsearch 、Kibana、Logstash elasticsearch导入中文分词器 Logstash修改es数据库ip及创建索引名配置 一、elasticsearch数据库的结构 和mysql作比较&#xff0c;mysql中的数据库的二维表相当于es数据库的index索引结构&#xff1b;mysql数据库的二…

大数据处理从零开始————4.认识HDFS分布式文件系统

1.分布式文件系统HDFS 1.1 认识HDFS 当单台服务器的存储容量和计算性能已经无法处理大文件时&#xff0c;分布式文件系统应运而生。什么是分布式系统&#xff0c;分布式系统是由多个独立的计算机或节点组成的系统&#xff0c;这些计算机通过网络连接&#xff…

Mysql(五) --- 数据库设计

文章目录 前言1.范式1.1.第一范式1.1.1 定义1.1.2.例子 1.2.第二范式1.2.1 定义1.2.2 例子1.2.3.不满足第二范式可能会出现的问题 1.3.第三范式1.3.1 定义2.3.2 示例 2. 设计过程3. 实体-关系图3.1 E-R图的基本组成3.2 关系的类型3.2.1 一对一关系(1:1)3.2.2 ⼀对多关系(1:N)3.…

paimon,基础查询语句测试

基础设置 -- 创建catalog/加载catalog&#xff0c;如果这个catalog已经存在就不会创建&#xff0c;自动加载元数据信息CREATE CATALOG fs_paimon_catalog WITH ( type paimon, warehouse hdfs://wsl01:8020/paimon/catalog ); -- 使用catalog use catalog fs_paimon_catalog…

Java虚拟机(JVM)

目录 内存区域划分堆&#xff08;Heap&#xff09;方法区&#xff08;Method Area&#xff09;程序计数器&#xff08;Program Counter Register&#xff09;虚拟机栈&#xff08;VM Stack&#xff09;本地方法栈&#xff08;Native Method Stack&#xff09; 类加载的过程类加…

[C++]使用纯opencv部署yolov11-seg实例分割onnx模型

【算法介绍】 在C中使用纯OpenCV部署YOLOv11-seg进行实例分割是一项具有挑战性的任务&#xff0c;因为YOLOv11通常是用PyTorch等深度学习框架实现的&#xff0c;而OpenCV本身并不直接支持加载和运行PyTorch模型。然而&#xff0c;可以通过一些间接的方法来实现这一目标&#x…

运维工具之ansible

Ansible 1.什么是ansible? ​ ansible是基于ssh架构的自动化运维工具&#xff0c;由python语言实现&#xff0c;通过ansible可以远程批量部署等。 2.部署前提 ​ 控制端需要安装ansible,被控制端要开启ssh服务&#xff0c;并允许远程登录&#xff0c;被管理主机需要安装py…

卸载PLSQL及标准卸载流程

目录 1. 卸载PLSQL2. 删除注册表3. 删除数据信息 1. 卸载PLSQL 等待进度条走完 2. 删除注册表 regedit 右击删除 3. 删除数据信息 由于AppData是隐藏文件&#xff0c;需要勾选隐藏的项目。 重启电脑&#xff0c;PLSQL就卸载成功了。

浏览器和客户端结合的erp系统,java控制浏览器操作自动登录,socket客户端通信进行表单赋值

java做一个toB的客户端操作系统&#xff0c;客户端和web的结合&#xff1b; 主要是使用java编写客户端代码&#xff0c;采用selenium控制浏览器&#xff0c;主要是用到selenium自动化测试的功能&#xff1b; javaEE 项目调用 selenium使用谷歌控件chromedriver.exe控制浏览器…

使用Java调用OpenAI API并解析响应:详细教程

使用Java调用OpenAI API并解析响应&#xff1a;详细教程 在现代应用程序中&#xff0c;API调用是一个非常常见的任务。本文将通过一个完整的示例&#xff0c;讲解如何使用Java调用OpenAI的ChatGPT API&#xff0c;并通过ObjectMapper处理JSON响应。本文的示例不仅适用于OpenAI…

网络参考模型

OSI七层网络参考模型 OSI模型仅作为参考&#xff0c;现实中并不用&#xff0c;OSI模型的目的是为了解决主机之间的网络通讯。 1. 物理层&#xff1a; 物理层将由比特&#xff08;0和1&#xff09;组成的数据用不同的媒介&#xff08;电、光或其他形式的电磁波&#xff09;传输…

黑马软件测试第一篇_测试理论

概念 使用技术手段验证软件功能是否符合需求 测试种类 功能测试 自动化测试 接口测试 性能测试 按测试阶段划分 单元测试&#xff1a;针对程序源码进行测试 集成测试&#xff1a;又称接口测试&#xff0c;针对模块之间访问地址进行测试 系统测试&#xff1a;对整个系统进行…

京东零售数据湖应用与实践

作者&#xff1a;陈洪健&#xff1a;京东零售大数据架构师&#xff0c;深耕大数据 10 年&#xff0c;2019 年加入京东&#xff0c;主要负责 OLAP 优化、大数据传输工具生态、流批一体、SRE 建设。 当前企业数据处理广泛采用 Lambda 架构。Lambda 架构的优点是保证了数据的完整性…

YOLO的相关改进机制

我的面包多平台有多种关于YOLO的改进&#xff0c;大家尽早关注&#xff0c;不迷路

【宽字节注入】

字符编码 url 编码 GBK编码 utf8 编码 宽字节注入 php中的转译函数 宽字节注入介绍 练习 正常输入没有回显&#xff1a; 没有回显 usernameadmin&passwordadmin 闭合单引号&#xff0c;依旧没有回显 usernameadmin and 11%23&passwordadmin利用宽字节尝试闭合,依旧…

查看SQL Server授权序列号通过SQL查询查看安装日志文件使用PowerShell查询

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

在Stable Diffusion WebUI中安装SadTalker插件时几种错误提示的处理方法

SD中的插件一般安装比较简单&#xff0c;但也有一些插件安装会比较难。比如我在安装SadTalker时&#xff0c;就遇到很多问题&#xff0c;一度放弃了&#xff0c;后来查了一些网上攻略&#xff0c;自己也反复查看日志&#xff0c;终于解决&#xff0c;不吐不快。 一、在Stable …

闪迪U盘误删的数据该怎么恢复呢?3个方法轻松解决

闪迪是一家全球知名的美国公司&#xff0c;也是全球最大的闪存数据存储卡产品供应商&#xff0c;其中&#xff0c;闪迪U盘作为其主要产品之一&#xff0c;因其便携性、大容量和高速传输能力而深受用户喜爱。然而&#xff0c;在平时存储重要数据的时候&#xff0c;会因为我们一系…

ElasticSearch备考 -- Update by query Reindex

一、题目 有个索引task&#xff0c;里面的文档长这样 现在需要添加一个字段all&#xff0c;这个字段的值是以下 a、b、c、d字段的值连在一起 二、思考 需要把四个字段拼接到一起&#xff0c;组成一个新的字段&#xff0c;这个就需要脚本&#xff0c; 这里有两种方案&#xff…

CSRF | GET 型 CSRF 漏洞攻击

关注这个漏洞的其他相关笔记&#xff1a;CSRF 漏洞 - 学习手册-CSDN博客 0x01&#xff1a;GET 型 CSRF 漏洞攻击 —— 理论篇 GET 型 CSRF 漏洞是指攻击者通过构造恶意的 HTTP GET 请求&#xff0c;利用用户的登录状态&#xff0c;在用户不知情的情况下&#xff0c;诱使浏览器…