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

news2024/11/30 12:39:48

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


【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.coloradmin.cn/o/1447577.html

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

相关文章

js中事件循环的详解

文章目录 一、是什么二、宏任务与微任务微任务宏任务 三、async与awaitasyncawait 四、流程分析 一、是什么 首先&#xff0c;JavaScript是一门单线程的语言&#xff0c;意味着同一时间内只能做一件事&#xff0c;但是这并不意味着单线程就是阻塞&#xff0c;而实现单线程非阻…

爬虫——ajax和selenuim总结

为什么要写这个博客呢&#xff0c;这个代码前面其实都有&#xff0c;就是结束了。明天搞个qq登录&#xff0c;这个就结束了。 当然也会更新小说爬取&#xff0c;和百度翻译&#xff0c;百度小姐姐的爬取&#xff0c;的对比爬取。总结嘛&#xff01;&#xff01;&#xff01;加…

智能优化算法 | Matlab实现飞蛾扑火(MFO)(内含完整源码)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 智能优化算法 | Matlab实现飞蛾扑火(MFO)(内含完整源码) 源码设计 %%%% clear all clc SearchAgents_no=100; % Number of search ag

深入浅出解析指针:从概念到实践

在编程的世界中&#xff0c;指针是一个非常重要且强大的工具。无论你是初学者还是经验丰富的开发者&#xff0c;理解并熟练使用指针都将极大地提升你的编程能力。今天&#xff0c;我们就来一起探讨指针的奥秘。 一、指针的基本概念 首先&#xff0c;我们需要明白&#xff0c;…

C++进阶(十六)特殊类设计

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、请设计一个类&#xff0c;不能被拷贝二、请设计一个类&#xff0c;只能在堆上创建对象三、…

从零开始:Linux下的Miniconda安装教程

&#x1f680;从零开始&#xff1a;Linux下的Miniconda安装教程&#x1f680; &#x1f335;文章目录&#x1f335; &#x1f333;引言&#x1f333;&#x1f333;二、Miniconda简介&#xff1a;开启您的数据科学之旅的得力助手&#xff01; &#x1f333;&#x1f333;三、Lin…

【前沿技术杂谈:迁移学习】欧洲人工智能法案对人工智能开发者的意义 [2023 年 12 月更新]

【前沿技术杂谈&#xff1a;迁移学习】欧洲人工智能法案对人工智能开发者的意义 [2023 年 12 月更新&#xff3d; 定义、一般原则和禁止做法人工智能系统开发者基于风险的义务固定和通用人工智能开发人员&#xff08;第 3/28 条&#xff09;基础模型的提供者&#xff08;第 28b…

C++入门篇——类与对象重点解析(下篇)

1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 class Date { public: Date(int year, int month, int day) {_year year;_month month;_day day; } private:int _year;int _m…

Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务

目录: OpenID 与 OAuth2 基础知识Blazor wasm Google 登录Blazor wasm Gitee 码云登录Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasmBlazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端…

全国计算机等级考试二级,MySQL数据库考试大纲(2023年版)

基本要求&#xff1a; 1.掌握数据库的基本概念和方法。 2.熟练掌握MySQL的安装与配置。 3.熟练掌握MySQL平台下使用&#xff33;&#xff31;&#xff2c;语言实现数据库的交互操作。 4.熟练掌握 MySQL的数据库编程。 5.熟悉 PHP 应用开发语言&#xff0c;初步具备利用该语言进…

下一代块存储重新定义任务关键型存储架构

HPE 宣布全面推出基于 HPE Alletra Storage MP 构建的 HPE GreenLake for Block Storage 第 3 版&#xff0c;提供业界首款分解式横向扩展块存储&#xff0c;并提供 100% 数据可用性保证。这种独特的块存储产品由共享一切存储架构提供支持&#xff0c;并通过 HPE GreenLake 云平…

OCP的operator——(1)概述

文章目录 概述了解Operator什么是Operator为何使用OperatorOperator FrameworkOperator成熟度模型 Operator Framework 打包格式Bundle格式Manifest注解依赖关于opm CLI 基于文件的目录RukPak Operator Framework常用术语表常见Operator Framework术语BundleBundle imageCatalo…

腾讯云4核8G服务器能支持多少人访问?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…

Java+SpringBoot+Vue:高校科研管理的技术革新

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

ubuntu22.04@laptop OpenCV Get Started: 007_color_spaces

ubuntu22.04laptop OpenCV Get Started: 007_color_spaces 1. 源由2. 颜色空间2.1 RGB颜色空间2.2 LAB颜色空间2.3 YCrCb颜色空间2.4 HSV颜色空间 3 代码工程结构3.1 C应用Demo3.2 Python应用Demo 4. 重点分析4.1 interactive_color_detect4.2 interactive_color_segment4.3 da…

docker 2:安装

docker 2&#xff1a;安装 ‍ ubuntu 安装 docker sudo apt install docker.io‍ 把当前用户放进 docker 用户组&#xff0c;避免每次运行 docker 命都要使用 sudo​ 或者 root​ 权限。 sudo usermod -aG docker $USER​id $USER ​看到用户已加入 docker 组 ​​ ‍ …

【深度学习】S2 数学基础 P1 线性代数(上)

目录 基本数学对象标量与变量向量矩阵张量降维求和非降维求和累计求和 点积与向量积点积矩阵-向量积矩阵-矩阵乘法 深度学习的三大数学基础 —— 线性代数、微积分、概率论&#xff1b; 自本篇博文以下几遍博文&#xff0c;将对这三大数学基础进行重点提炼。 本节博文将介绍线…

LeetCode、72. 编辑距离【中等,二维DP】

文章目录 前言LeetCode、72. 编辑距离【中等&#xff0c;二维DP】题目链接与分类二维DP 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容…

C++笔记1:操纵符输入输出

C操纵符用来控制输出控制&#xff0c;一是输出的形式&#xff0c;二是控制补白的数量和位置。本文记录一下&#xff0c;在一些笔试的ACM模式可能有用。其中1-4节的部分是关于格式化输入输出操作&#xff0c;5-6节的部分是关于未格式化输入输出操作。 1. 控制布尔值的格式 一般…