【教程】C++语言基础学习笔记(九)——指针

文首标志
写在前面:
如果文章对你有帮助,记得点赞关注加收藏一波,利于以后需要的时候复习,多谢支持!


【C++语言基础学习】系列文章

第一章 《项目与程序结构》
第二章 《数据类型》
第三章 《运算符》
第四章 《流程控制》
第五章 《Vector向量》
第六章 《String字符串》
第七章 《Array数组》
第八章 《函数》
第九章 《指针》
第十章 《结构体》


文章目录

  • 【C++语言基础学习】系列文章
  • 一、指针定义
  • 二、特殊指针
    • (一)空指针
    • (二)野指针
    • (三)const修饰指针
  • 三、指针与数组
  • 四、指针与函数


一、指针定义

指针(Pointer)是C++中的一种数据类型,用于存储变量的内存地址。它提供了直接访问内存位置的功能,并可以用于实现高效的数据结构和操作。
指针变量存储着其他变量的内存地址,可以通过解引用操作符*来访问指向的内存地址上存储的值。解引用操作符用于返回指针指向位置的值。
在C++中,可以使用以下语法来定义指针变量。

数据类型* 指针变量名;

以下是简单的示例。

// 定义变量
int a = 10;
// 定义指针
int* p;
// 让指针记录变量a的地址
p = &a;
cout << "a的值为:" << a << endl;
cout << "a的地址为:" << &a << endl;
cout << "指针p:" << p << endl;
// 使用指针
*p = 1000;
cout << "通过指针更改后a的值为:" << a << endl;
cout << "解引用后的*p:" << *p << endl;

返回结果如下。

a的值为:10
a的地址为:0000000B8CB6FA64
指针p:0000000B8CB6FA64
通过指针更改后a的值为:1000
解引用后的*p:1000

从示例可以看到,定义了一个变量后,可以通过定义指针的方式找到变量的储存空间(地址),表现在取址后的变量&a和指针p直接储存的信息相同;而通过解引用的方式可以找到指针指向的内存中的数据,从而可以更改其数据,这里就是通过解引用指针*p,向此数据重新赋值了1000的值,再次输出可以发现解引用指针*p与原本的变量a都随之改变。
其中,指向变量a的指针定义方式也可以简化为如下所示。

int* p = &a;

而指针既然也属于一种数据类型,同样也会占用一定的内存空间。一般情况下,指针变量的大小为机器的字长(即指针所占的位数),通常为4个字节(32位系统)或8个字节(64位系统)。指针变量保存的是一个内存地址,这个地址指向存储在内存中的某个变量或对象。因此,即使指针变量本身只占用很小的空间,它所引用的对象可能会占用更多的空间。

cout << "sizeof(int*) = " << sizeof(int*) << endl;
cout << "sizeof(float*) = " << sizeof(float*) << endl;
cout << "sizeof(double*) = " << sizeof(double*) << endl;
cout << "sizeof(char*) = " << sizeof(char*) << endl;

使用x86调试器(32位)返回结果如下。

sizeof(int*) = 4
sizeof(float*) = 4
sizeof(double*) = 4
sizeof(char*) = 4

使用x64调试器(64位)返回结果如下。

sizeof(int*) = 8
sizeof(float*) = 8
sizeof(double*) = 8
sizeof(char*) = 8

可以看到,无论是32位还是64位,各种数据类型的指针占用的字节数都一样,这说明无论指向什么数据类型,其储存地址的指针所占用的内存都是相同的,不会因为指向的数据类型本身的数据大小而改变。

二、特殊指针

除了指向各种数据类型的普通指针,在C++中同样还有着特殊的指针类型。

(一)空指针

空指针(Null Pointer)是指没有指向任何有效对象或者函数的指针,也就是指向内存中编号为0的空间(0~255是系统储存的空间,是无法访问的),其用途主要是初始化指针变量。在C++中,可以用常量值0或者特殊关键字nullptr表示空指针。
需要注意的是,空指针指向的内存是不可以访问的。

int* ptr = nullptr; // 初始化为空指针

当定义一个指针变量时,如果没有为其赋予初始值,可以将其初始化为空指针,这避免了指针悬空的风险。

(二)野指针

野指针(Dangling Pointer)是指指针仍然保留在内存中,但指向的内存已经被释放或者无效的情况。使用野指针是一种常见的编程错误,可能导致程序崩溃、错误的读写内存数据或产生不可预测的行为。

int* p = (int*)0x1100;

例如以上的代码,使用(int*)可以手动将一段地址0x1100输入到指针内,但由于这样的地址并没有通过系统的申请,以至于虽然语法正确,编译器仍然无法为这样一个非法地址分配空间,进而导致系统报错。

(三)const修饰指针

const修饰指针有三种情况。

  1. const修饰指针——常量指针
  2. const修饰常量——指针常量
  3. const既修饰指针,又修饰常量

对于第一种情况的常量指针,其特点是指针的指向可以修改,但是指针指向的值不可以修改。
以下是简单的示例。

int a = 10;
int b = 10;
const int* p = &a;
*p = 20;// 错误,指针指向的值从10到了20,值发生了改变
p = &b;// 正确,指针的指向从a转移到了b,但值为10没有发生改变

从代码可以看到,此示例const关键字后是int*这个确定的内存空间,即指针指向的常量。

int a = 10;
int b = 10;
int* const p = &a;
*p = 20;// 正确,指针指向的值从10到了20,但指向a没有发生改变
p = &b;// 错误,指针的指向从a转移到了b,指向发生了改变

而对于第二种情况,此示例const关键字后是p = &a这个指向确定的指针,即指针本身。

int a = 10;
int b = 10;
const int* const p = &a;
*p = 20;// 错误,指针指向的值从10到了20,值发生了改变
p = &b;// 错误,指针的指向从a转移到了b,指向发生了改变

综合以上两个案例即为第三种情况:此示例的两个const关键字既有int*这个确定的内存空间,又有p = &a这个指向确定的指针,所以此时指针的指向和值都被锁定,无法发生改变。

三、指针与数组

在C++中,同样可以利用指针来访问数组。

int arr[10] = { 1,2,3,4,5,6,7,8,9 };
cout << "第一个元素为:" << arr[0] << endl;
int* p = arr;
cout << "利用指针访问第一个元素:" << *p << endl;
p++;
cout << "利用指针访问第二个元素:" << *p << endl;

返回结果如下。

第一个元素为:1
利用指针访问第一个元素:1
利用指针访问第二个元素:2

以上示例代码中,首先定义了一个数组,由于本系列第七章已经证明数组本身的首地址既是第一行元素的首地址也是第一个元素的首地址,所以指针p直接指向数组arr本身就可以直接得到第一个元素的首地址;而p++则将首地址增加了4个字节,由此得到第二个元素的首地址,输出解引用的指针即可访问相应元素。

四、指针与函数

在本系列第八章中已经说明,函数的值传递只会令函数形参发生改变却不会改变实参。然而,通过指针的地址传递,函数的实参同样可以被改变。

#include <iostream>
using namespace std;void swap(int* p1, int* p2)
{int temp = *p1;*p1 = *p2;*p2 = temp;
}int main()
{int a = 10;int b = 20;swap(&a, &b);cout << "a = " << a << endl;cout << "b = " << b << endl;
}

返回结果如下。

a = 20
b = 10

在此次定义的swap()函数中,定义的函数内部通过解引用指针的方式重新给内存数据赋值,使得最后的结果表现为作为实参的变量ab的值也发生了改变,这就是地址传递。


我是EC,一个永远在学习中的探索者,关注我,让我们一起进步!

文末标志

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

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

相关文章

【学网攻】 第(27)节 -- HSRP(热备份路由器协议)

系列文章目录 目录 系列文章目录 文章目录 前言 一、HSRP(热备份路由器协议)是什么&#xff1f; 二、实验 1.引入 实验目标 实验背景 技术原理 实验步骤 实验设备 实验拓扑图 实验配置 实验验证 文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交…

FT2232调试记录(3)

FT2232调试记录&#xff08;1&#xff09;: FT2232调试记录&#xff08;2&#xff09;: FT2232调试记录&#xff08;3&#xff09;: FT2232 SPI读写函数: 参照SPI提供的文档&#xff1a; 工程&#xff1a; SPI 写函数&#xff1a; FT_STATUS write_byte(FT_HANDLE handle…

tkinter-TinUI-xml实战(10)展示画廊

tkinter-TinUI-xml实战&#xff08;10&#xff09;展示画廊 引言声明文件结构核心代码主界面统一展示控件控件展示界面单一展示已有展示多类展示 最终效果在这里插入图片描述 ![](https://img-blog.csdnimg.cn/direct/286fcaa2fa5648a992a0ac79b4efad82.png) ………… 结语 引言…

问题:3【单选题】实现职业理想的一般步骤是()。 #媒体#媒体

问题&#xff1a;3【单选题】实现职业理想的一般步骤是()。 A、创业-立业-择业 B、择业-创业-立业 C、择业-立业-创业 D、立业-择业-创业 参考答案如图所示

Zabbix图形中文乱码问题(显示口口)解决办法

一 切换到zabbix安装目录assets/fonts下&#xff0c;下载字体 这里使用是nginxphp作为zabbix-web展示&#xff0c;使用find 命令查找 进入目录下&#xff0c;将原有字体备份&#xff0c;下载msyh字体 wget https://www.xxshell.com/download/sh/zabbix/ttf/msyh.ttf 二 修改配…

华为OD机试 - 分配土地( Python C C++ JavaGo JS PHP)

题目描述 从前有个村庄&#xff0c;村民们在各种田地上插上小旗子&#xff0c;每个旗子上都标识了一个数字。现在&#xff0c;村民们想要找出一个包含相同数字的最小矩形区域&#xff0c;并将这块土地分配给对村庄做出巨大贡献的村民。我们需要找出这个矩形区域的最大面积。 …

修改npm 的运行命令详解

在Node.js和npm中&#xff0c;你可以通过修改package.json文件中的scripts部分来定义和运行自定义的npm脚本。这些脚本可以是任何你希望在项目中运行的命令&#xff0c;包括启动服务器、运行测试、构建项目等。下面是一些修改npm运行命令的详解和代码示例。 修改npm运行命令的…

python 基础知识点(蓝桥杯python科目个人复习计划41)

今日复习内容&#xff1a;动态规划&#xff08;基础&#xff09; 动态规划是一种解决多阶段决策过程中最优化问题的数学方法和算法思想。它通常用于解决具有重叠子问题和最优子结构性质的问题&#xff0c;通常将问题划分为相互重叠的子问题&#xff0c;利用子问题的解来求解原…

Git分支和迭代流程

Git分支 feature分支&#xff1a;功能分支 dev分支&#xff1a;开发分支 test分支&#xff1a;测试分支 master分支&#xff1a;生产环境分支 hotfix分支&#xff1a;bug修复分支。从master拉取&#xff0c;修复并测试完成merge回master和dev。 某些团队可能还会有 reale…

移动机器人激光SLAM导航(五):Cartographer SLAM 篇

参考 Cartographer 官方文档Cartographer 从入门到精通 1. Cartographer 安装 1.1 前置条件 推荐在刚装好的 Ubuntu 16.04 或 Ubuntu 18.04 上进行编译ROS 安装&#xff1a;ROS学习1&#xff1a;ROS概述与环境搭建 1.2 依赖库安装 资源下载完解压并执行以下指令 https://pa…

Vue项目创建和nodejs使用

Vue项目创建和nodejs使用 一、环境准备1.1.安装 node.js【下载历史版本node-v14.21.3-x64】1.2.安装1.3.检查是否安装成功&#xff1a;1.4.在Node下新建两个文件夹 node_global和node_cache并设置权限1.5.配置npm在安装全局模块时的路径和缓存cache的路径1.6.配置系统变量&…

Linux多线程[二]

引入知识 进程在线程内部执行是OS的系统调度单位。 内核中针对地址空间&#xff0c;有一种特殊的结构&#xff0c;VM_area_struct。这个用来控制虚拟内存中每个malloc等申请的空间&#xff0c;来区别每个malloc的是对应的堆区哪一段。OS可以做到资源的精细度划分。 对于磁盘…

C#调用WechatOCR.exe实现本地OCR文字识别

最近遇到一个需求&#xff1a;有大量的扫描件需要还原为可编辑的文本&#xff0c;很显然需要用到图片OCR识别为文字技术。本来以为这个技术很普遍的&#xff0c;结果用了几个开源库&#xff0c;效果不理想。后来&#xff0c;用了取巧的方法&#xff0c;直接使用了WX的OCR识别模…

算法与数据结构

算法与数据结构 前言 什么是算法和数据结构&#xff1f; 你可能会在一些教材上看到这句话&#xff1a; 程序 算法 数据结构 算法&#xff08;Algorithm&#xff09;&#xff1a;是指解题方案的准确而完整的描述&#xff0c;是一系列解决问题的清晰指令&#xff0c;算法代…

【Tomcat】:One or more listeners failed to start.报错解决方案

报错信息:One or more listeners failed to start. Full details will be found in the appropriate container log file. 具体就是web.xml此配置报错: 服务器启动错误Tomcat:One or more listeners failed to start.报错解决方案 IDEA:在使用IDEA运行SSM项目的时候 , Tomcat运…

ChatGpt报错:We ran into an issue while authenticating you解决办法

在登录ChatGpt时报错&#xff1a;Oops&#xff01;,We ran into an issue while authenticating you.(我们在验证您时遇到问题)&#xff0c;记录一下解决过程。 完整报错&#xff1a; We ran into an issue while authenticating you. If this issue persists, please contact…

怎么使用ChatGPT提高工作效率?

怎么使用ChatGPT提高工作效率&#xff0c;这是一个有趣的话题。 相信不同的人有不同的观点&#xff0c;大家的知识背景和从事的工作都不完全相同&#xff0c;所以最终ChatGPT能起到的作用也不一样。 在编程过程中&#xff0c;如果我们要找一个库&#xff0c;我们最先做的肯定…

[缓存] - 2.分布式缓存重磅中间件 Redis

1. 高性能 尽量使用短key 不要存过大的数据 避免使用keys *&#xff1a;使用SCAN,来代替 在存到Redis之前压缩数据 设置 key 有效期 选择回收策略(maxmemory-policy) 减少不必要的连接 限制redis的内存大小&#xff08;防止swap&#xff0c;OOM&#xff09; slowLog …

C语言第二十三弹---指针(七)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1、sizeof和strlen的对比 1.1、sizeof 1.2、strlen 1.3、sizeof 和 strlen的对比 2、数组和指针笔试题解析 2.1、⼀维数组 2.2、二维数组 总结 1、si…

每日五道java面试题之java基础篇(八)

第一题.CopyOnWriteArrayList的底层原理是怎样的 ⾸先CopyOnWriteArrayList内部也是⽤过数组来实现的&#xff0c;在向CopyOnWriteArrayList添加元素时&#xff0c;会复制⼀个新的数组&#xff0c;写操作在新数组上进⾏&#xff0c;读操作在原数组上进⾏并且&#xff0c;写操作…