【教程】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,一个永远在学习中的探索者,关注我,让我们一起进步!

文末标志

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面向智算服务,构建可观测体系最佳实践

作者&#xff1a;蓟北 构建面向 AI、大数据、容器的可观测体系 &#xff08;一&#xff09;智算服务可观测概况 对于越来越火爆的人工智能领域来说&#xff0c;MLOps 是解决这一领域的系统工程&#xff0c;它结合了所有与机器学习相关的任务和流程&#xff0c;从数据管理、建…

【C语言】内存函数memcpy和memmove的功能与模拟实现

1.memcpy 功能&#xff1a;把source指向的前num个字节内容拷贝到destination指向的位置去&#xff0c;可以拷贝任意类型的数据。 注&#xff1a;1.memcpy并不关心\0&#xff0c;毕竟传的也不一定是字符串&#xff0c;因此拷贝过程中遇到\0也不会停下来。 2.num的单位是字节&a…

基于Echarts的可视化项目

整体的效果 概览区域 <!-- 概览区域模块制作 --><div class"panel overview"><div class"inner"><ul><li><h4>2190</h4><span><i class"icon-dot"></i>设备总数</span></…

Java 基于springboot+vue在线外卖点餐系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

深度学习的新进展:探索人工智能的未来

文章目录 &#x1f4d1;引言深度学习技术概述计算机视觉领域的深度应用自然语言处理的深度革命跨领域应用的深度拓展深度学习的挑战与未来展望结语 &#x1f4d1;引言 在科技日新月异的今天&#xff0c;深度学习作为人工智能领域的一颗璀璨明珠&#xff0c;正在引领着技术创新…

ElasticSearch分词器和相关性详解

目录 ES分词器详解 基本概念 分词发生时期 分词器的组成 切词器&#xff1a;Tokenizer 词项过滤器&#xff1a;Token Filter 停用词 同义词 字符过滤器&#xff1a;Character Filter HTML 标签过滤器&#xff1a;HTML Strip Character Filter 字符映射过滤器&#x…

linux系统zabbix监控配置电话告警

电话报警 睿象云官网操作zabbix-server主机操作睿象云操作zabbix-server的web页面操作 睿象云官网&#xff1a;https://www.aiops.com/ 睿象云官网操作 登录睿象云平台后点击智能告警平台 在集成栏选择监控工具选择zabbix 填写应用名称保存并获取key zabbix-server主机操…

php基础学习之文件包含

描述 在一个php脚本中&#xff0c;将另一个php文件包含进来&#xff0c;合作实现某种功能 这个描述看起来似乎和C/Java等语言的头文件/包有点类似&#xff0c;但本质是不一样的 打个比方&#xff1a; C/Java的头文件/包更像是一个工具箱&#xff0c;存放各种很完善的工具&#…

找不到目标和方向,怎么办?

现代社会里&#xff0c;许多人常见的症状&#xff0c;就是「空心病」。 什么是空心病呢&#xff1f;类似这样&#xff1a; 我知道要有目标&#xff0c;但我就是不知道想做什么&#xff0c;感觉对一切事物都提不起兴趣&#xff0c;没有动力&#xff0c;怎么办&#xff1f; 这个…

骑士遍历初级版

时间限制&#xff1a;1秒 内存限制&#xff1a;128M 题目描述 如图&#xff0c;从左下角A点出发&#xff0c;马只能向右走&#xff0c;根据马走日字的规则&#xff0c;究竟如何走才能到达右上角B点 输入描述 两个整数x、y&#xff0c;代表右上角B点的坐标&#xff0c…

AcWing 112. 雷达设备(区间贪心)

[题目概述] 假设海岸是一条无限长的直线&#xff0c;陆地位于海岸的一侧&#xff0c;海洋位于另外一侧。 每个小岛都位于海洋一侧的某个点上。 雷达装置均位于海岸线上&#xff0c;且雷达的监测范围为 d&#xff0c;当小岛与某雷达的距离不超过 d 时&#xff0c;该小岛可以被雷…

Excel练习:日历

Excel练习&#xff1a;日历 ‍ 题目&#xff1a;制作日历 ‍ ​​ 用rows和columns函数计算日期单元格偏移量 一个公式填充所有日期单元格 ​​ ‍

FT2232调试记录(2)

FT2232调试记录 &#xff08;1&#xff09;获取当前连接的FTDI设备通道个数:&#xff08;2&#xff09;获取当前连接的设备通道的信息:&#xff08;3&#xff09;配置SPI的通道:&#xff08;4&#xff09;如何设置GPIO:&#xff08;5&#xff09;DEMO测试&#xff1a; FT2232调…

Unity 工具之 UniWebView 内嵌网页/浏览器到应用中,并且根据UGUI大小放置(简单适配UGUI)

目录 Unity 工具之 UniWebView 内嵌网页/浏览器到应用中&#xff0c;并且根据UGUI大小放置&#xff08;简单适配UGUI&#xff09; 一、简单介绍 二、UniWebView 组件上的几个参数属性选项介绍 三、一些关键接口介绍 四、Transition 五、Memory Management&#xff08;内存…

OJ刷题:找出单身狗1,2【建议收藏点赞】

目录 1. 单身狗12. 单身狗2 1. 单身狗1 代码实现&#xff1a; #include <stdio.h>int main() {int arr[] { 1,2,3,2,1 };int sz sizeof(arr) / sizeof(arr[0]);int i 0;int tmp 0;for (i 0; i < sz; i){tmp ^ arr[i];}printf("%d\n", tmp);return 0; …

微信小程序介绍、账号申请、开发者工具目录结构详解及小程序配置

目录 一、微信小程序介绍 1.什么是小程序&#xff1f; 2.小程序可以干什么&#xff1f; 3.微信小程序特点 二、账号申请 1.账号注册 2.测试号申请 三、安装开发工具 四、开发小程序 五、目录结构 JSON 配置 小程序配置 app.json 工具配置 project.config.json 页…

PHP毕业设计图片分享网站76t17

图片分享网站主要是为了提高工作人员的工作效率和更方便快捷的满足用户&#xff0c;更好存储所有数据信息及快速方便的检索功能&#xff0c;对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑用户的可操作性&#xff0c;遵循开发的系统优化的原则&#xff0c;…

Linux 查看 系统基本信息 uname

基本用法&#xff1a; 在终端中输入"uname"即可显示系统的内核名称。 可以结合不同的参数使用&#xff0c;获取更详细的系统信息。 常见参数&#xff1a; “-s”&#xff1a;显示操作系统名称。 “-n”&#xff1a;显示网络节点主机名。 “-r”&#xff1a;显示内核版…

【初中生讲机器学习】9. 我是怎么用朴素贝叶斯实现垃圾邮件分类的?真的超全!

创建时间&#xff1a;2024-02-14 最后编辑时间&#xff1a;2024-02-15 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名初三学生&#xff0c;热爱计算机和数学&#xff0c;我们一起加…

Java学习第十四节之多维数组和Arrays类讲解

多维数组 package array;public class ArrayDemo05 {public static void main(String[] args) {//[4][2] 面向对象/*1,2 array[0]2,3 array[1]3,4 array[2]4,5 array[3]*/int[][] array {{1,2},{2,3},{3,4},{4,5}};for (int i 0; i <array.length; i) {for (int…