深入理解 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.rhkb.cn/news/447207.html

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

相关文章

【算法】哈希表:49.字母异位词分组

目录 1、题目链接 2、题目介绍 3、解法 初始化设定--图解 步骤图解 4、代码 1、题目链接 49. 字母异位词分组 - 力扣&#xff08;LeetCode&#xff09; 2、题目介绍 3、解法 字母异位词的本质是字符相同但排列不同。因此&#xff0c;我们可以对字符串进行排序&#xf…

wordpress使用popup弹窗插件的对比

您在寻找最好的 WordPress 弹出插件吗&#xff1f;大多数网站利用某种形状或形式的弹出窗口来将访问者指向他们希望他们去的地方。例如&#xff0c;这可能用于结帐、电子邮件订阅或用于生成潜在客户。 表现 弹出插件会减慢您的网站速度。当插件使用 WordPress 跟踪弹出窗口的…

K8S配置MySQL主从自动水平扩展

前提环境 操作系统Ubuntu 22.04 K8S 1.28.2集群&#xff08;1个master2个node&#xff09; MySQL 5.7.44部署在K8S的主从集群 metrics-server v0.6.4 概念简介 在K8s中扩缩容分为两种 ●Node层面&#xff1a;对K8s物理节点扩容和缩容&#xff0c;根据业务规模实现物理节点自动扩…

《大规模语言模型从理论到实践》第一轮学习--强化学习(RLHF、PPO)

个人学习笔记,如有错误欢迎指出。 一、强化学习的意义 RLHF(Reinforcement Learning from Human Feedback):强化学习(Reinforcement Learning)结合人类反馈(Human Feedback)来微调大语言模型。 大语言模型的训练步骤包括:预训练、指令微调(SFT)、对齐。 对齐(a…

MWD天气图像多分类数据集,用于图像分类-共6个类别,共60000张图像数据 ,含有模型

MWD天气图像多分类数据集&#xff0c;用于图像分类- MWD天气图像多分类数据集&#xff0c;用于图像分类-共6个类别&#xff0c;共60000张图像数据 &#xff0c;含有模型 MWD天气图像多分类数据集及模型介绍 数据集概述 名称&#xff1a;MWD天气图像多分类数据集图像数量&…

使用node.js控制CMD命令——修改本机IP地址

设置每次打开cmd命令行窗口都是以管理员身份运行&#xff1a; 1. 按下Ctrl Shift Esc键组合&#xff0c;打开任务管理器。 2. 在任务管理器中&#xff0c;点击“文件”菜单&#xff0c;选择“运行新任务”。 3. 在“创建新任务”对话框中&#xff0c;输入cmd&#xff0c;勾…

基于知识图谱的宁夏非遗问答系统

八维视角探索宁夏非遗文化——基于知识图谱的非遗问答系统 作为一名程序员&#xff0c;能将大数据与文化传承结合&#xff0c;赋予历史新的生命&#xff0c;是件多么振奋的事&#xff01;今天给大家介绍的是一款基于知识图谱技术的宁夏非物质文化遗产问答系统。无论你是学术研…

Scrapy网络爬虫基础

使用Spider提取数据 Scarpy网络爬虫编程的核心就是爬虫Spider组件&#xff0c;它其实是一个继承与Spider的类&#xff0c;主要功能设计封装一个发送给网站服务器的HTTP请求&#xff0c;解析网站返回的网页及提取数据 执行步骤 1、Spider生成初始页面请求&#xff08;封装于R…

【未公开0day】9.9付费进群系统 wxselect SQL注入漏洞【附poc下载】

免责声明&#xff1a;本文仅用于技术学习和讨论。请勿使用本文所提供的内容及相关技术从事非法活动&#xff0c;若利用本文提供的内容或工具造成任何直接或间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果均与文章作者及本账号无关。 fofa语…

Java Maven day1014

ok了家人们&#xff0c;今天学习了如何安装和配置Maven项目&#xff0c;我们一起去看看吧 一.Maven概述 1.1 Maven作用 Maven 是专门用于管理和构建 Java 项目的工具&#xff0c;它的主要功能有&#xff1a; 提供了一套标准化的项目结构 提供了一套标准化的构建流程&#x…

【2D/3D-Lidar-SLAM】 2D/3D激光SLAM以及GMapping 与 Cartographer

这里写自定义目录标题 1. 激光SLAM分类2. 2D Lidar SLAM3. 3D Lidar SLAM4. GMapping**1. GMapping 系统架构**1.1 **粒子滤波器Particle Filter**1.2 **运动模型Motion Model**1.3 **传感器模型Sensor Model**1.4 **地图更新Map Update**1.5 **重采样Resampling**1.6 **闭环检…

nbsaas vue3管理后台框架

nbsaas vue3管理后台框架 一、项目概述 Nbsaas Admin Vue 是一个基于 Vue.js 3.0 构建的轻量级后台管理系统&#xff0c;结合了现代前端技术栈的最佳实践&#xff0c;旨在帮助开发者快速构建具有高可扩展性和良好用户体验的后台管理系统。该项目拥有简洁的 UI 设计&#xff0…

【Linux快速入门(二)】Linux与ROS学习之编译基础(make编译)

目录 零.前置篇章 一.make的由来 二.安装make 三.编写Makefile 四.编译运行 五.删除可执行文件 零.前置篇章 第一篇【Linux快速入门】Linux与ROS学习之编译基础&#xff08;gcc编译&#xff09;_linuxros-CSDN博客 一.make的由来 "make"是一个用于自…

STL.string(中)

string 迭代器findswapsubstrrfindfind_first_of&#xff08;用的很少&#xff09;find_last_of&#xff08;用的很少&#xff09;find_first_not_of&#xff08;用的很少&#xff09; 迭代器 int main() {//正向迭代器string s1("hello world!");string::iterator i…

力扣 237. 删除链表中的节点【狸猫换太子】

题目 解题 该题中链表节点的值都是唯一的&#xff0c;且只给出待删除的节点 node&#xff0c;而没有给出 head&#xff0c;显然是不可以遍历链表找到相应值来进行删除节点的。注意到题目只要求给定节点的值不在链表中&#xff0c;且链表节点个数减少一个即可&#xff0c;并非严…

起吊机革新:协议转换器解锁安全与效率

重工起吊机设备在工业生产中扮演着至关重要的角色&#xff0c;但其在实际应用中面临着一系列痛点问题。这些问题不仅影响了起吊机的性能和安全性&#xff0c;还限制了生产效率的提升。我们自主研发的MG协议转换器能够高效解决这些痛点&#xff0c;同时MG协议转换器作为一种关键…

第十五届蓝桥杯C/C++学B组(解)

1.握手问题 解题思路一 数学方法 50个人互相握手 &#xff08;491&#xff09;*49/2 &#xff0c;减去7个人没有互相握手&#xff08;61&#xff09;*6/2 答案&#xff1a;1024 解题思路二 思路&#xff1a; 模拟 将50个人从1到50标号&#xff0c;对于每两个人之间只握一…

[Linux] 逐层深入理解文件系统 (2)—— 文件重定向

标题&#xff1a;[Linux] 逐层深入理解文件系统 &#xff08;2&#xff09;—— 文件重定向 个人主页水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、文件的读取和写入 二、文件重定向的本质 1.手动模拟重定向的过程——把标准输出重定向到redir.txt 2.重定向…

分享两种安装windows系统教程,学会后再也不需要花钱装系统了。

前期准备工作&#xff1a; 需要一个8G或16G的空U盘需要你安装的系统的镜像文件 一般是一个以 .iso 后缀结尾的文件 2.1 镜像文件获取方式 1&#xff09; 去windows 官网获取 2&#xff09;去 我告诉你 网址下载所需要的镜像文件 这个网址 分享了很多 我们常用的系统 大家可以按…

C++面向对象--------继承篇

目录 一.继承&#xff08;重点&#xff09; 1.1 概念 1.2 构造函数 1.2.1 派生类与基类的构造函数关系 1.2.2 解决方案 1.2.2.1 补充基类的无参构造函数 1.2.2.2 手动在派生类中调用基类构造函数 1.2.2.2.1 透传构造 1.2.2.2.2 委托构造 1.2.2.2.3 继承构造 1.3 对象…