【教程】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.mzph.cn/news/682363.shtml

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

相关文章

消息中间件特点

1.  消息中间件概念 消息中间件是消息传递的过程中保存消息的容器。 主要目的&#xff1a;提供路由并保证消息的传递&#xff1b;如果发送消息时接受者不可用&#xff0c;消息队列会保留信息&#xff0c;直到可以成功传递为止。 消息中间件保存消息也是有期限的。 2.  消息…

车载软件架构 —— Adaptive AUTOSAR软件架构

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师&#xff08;Wechat&#xff1a;gongkenan2013&#xff09;。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 本就是小人物&#xff0c;输了就是输了&#…

【Zigbee课程设计系列文章】Zigbee开发环境搭建

【Zigbee课程设计系列文章】Zigbee开发环境搭建 前言IAR 下载安装Z-Stack协议栈安装 &#x1f38a;项目专栏&#xff1a;【Zigbee课程设计系列文章】&#xff08;附详细使用教程完整代码原理图完整课设报告&#xff09; 前言 &#x1f451;由于无线传感器网络&#xff08;也即…

每日一练——月落乌啼算钱

题目&#xff1a; 举例&#xff1a; 输入&#xff1a;6&#xff0c;输出&#xff1a;8.00 最开始看到这道题还有点蒙&#xff0c;但是看到他的公式想起了斐波那契数列 1,1,2,3,5,8...... 由前两个数相加得到第三个数&#xff0c;为An2An1An。 可以得出这个题目中所给的通项就…

大更新!gpt加入记忆功能,可以记忆自己的提问啦!

2月14日凌晨&#xff0c;OpenAI在官网宣布&#xff0c;正在测试ChatGPT记住用户提问内容的能力&#xff0c;同时可以自由控制其内存。 该功能使用户不必频繁地提问相同的内容&#xff0c;ChatGPT都将记住那些内容并对长对话、个性化聊天等&#xff0c;例如&#xff0c;写长文小…

基于Python的HTTP隧道安全性分析:魔法背后的锁与钥匙

当我们谈论基于Python的HTTP隧道时&#xff0c;不禁让人想起那些神秘的魔法门。但是&#xff0c;在魔法背后&#xff0c;我们也需要确保安全性&#xff0c;就像需要确保魔法不会落入邪恶之手一样。那么&#xff0c;基于Python的HTTP隧道在安全性方面表现如何呢&#xff1f;让我…

小区开店的成功秘诀:如何满足老年人的需求?

在鲜奶吧行业摸爬滚打 5 年&#xff0c;我深切体会到&#xff0c;要在小区成功开店&#xff0c;满足老年人的需求至关重要。以下是我总结的一些经验&#xff0c;希望能给想开鲜奶吧或正在创业的朋友们提供有价值的参考。 一、产品特色与健康理念 1、产品特色&#xff1a; 提…

生成树技术华为ICT网络赛道

9.生成树 目录 9.生成树 9.1.生成树技术概述 9.2.STP的基本概念及工作原理 9.3.STP的基础配置 9.4.RSTP对STP的改进 9.5.生成树技术进阶 9.1.生成树技术概述 技术背景&#xff1a;二层交换机网络的冗余性与环路 典型问题1&#xff1a;广播风暴 典型问题2&#xff1a;MA…

深入理解C语言(4):文件操作详解

文章主题&#xff1a;文件操作详解&#x1f30f;所属专栏&#xff1a;深入理解C语言&#x1f4d4;作者简介&#xff1a;更新有关深入理解C语言知识的博主一枚&#xff0c;记录分享自己对C语言的深入解读。&#x1f606;个人主页&#xff1a;[₽]的个人主页&#x1f3c4;&#x…

洛谷_P1059 [NOIP2006 普及组] 明明的随机数_python写法

这道题的关键在于去重和排序&#xff0c;去重可以联想到集合&#xff0c;那排序直接使用sort方法。 n int(input()) data set(map(int,input().split( ))) data list(data) data.sort() print(len(data)) for i in data:print(i,end )

进阶C语言-动态内存管理

动态内存管理 &#x1f388;1.为什么存在动态内存分配&#x1f388;2.动态内存函数的介绍&#x1f52d;2.1malloc和free函数&#x1f52d;2.2calloc函数&#x1f52d;2.3realloc函数 &#x1f388;3.常见的动态内存错误&#x1f52d;3.1对NULL指针的解引用操作&#x1f52d;3.2…

PLC_博图系列☞FBFC

PLC_博图系列☞FB&FC 文章目录 PLC_博图系列☞FB&FC背景介绍FB&FC与C 类比博图中定义函数块 (FB)函数 (FC) 关键字&#xff1a; PLC、 西门子、 博图、 FC 、 FB 背景介绍 这是一篇关于PLC编程的文章&#xff0c;特别是关于西门子的博图软件。我并不是专业的P…

新项目,从0到1,SpringBoot+Vue.js权限管理系统,拿去做毕设

大家好&#xff0c;我是 jonssonyan 最近把以前做的权限管理系统重新整理了一下&#xff08;将一些不规范的地方规范了一下&#xff0c;并且在关键地方写了注释&#xff09;&#xff0c;代码全部开源&#xff0c;这个项目是以现在主流的前后端分离模式开发的&#xff0c;包含前…

面试经典150题——串联所有单词的子串(困难)

"Opportunities dont happen, you create them." ​ - Chris Grosser 1. 题目描述 2. 题目分析与解析 2.1 思路一——暴力求解 遇见这种可能刚开始没什么思路的问题&#xff0c;先试着按照人的思维来求解该题目。对于一个人来讲&#xff0c;我想要找到 s 字符串中…

AJAXJSON入门篇

AJAX&JSON 概念&#xff1a;AJAX(Asynchronous JavaScript And XML):异步的JavaScript和XML AJAX作用&#xff1a; 与服务器进行数据交换&#xff1a;通过AJAX可以给服务器发送请求&#xff0c;并获取服务器响应的数据 使用了AJAX和服务器进行通信&#xff0c;就可以使用H…

基于servlet编写的表白墙项目(后端代码 含数据库操作)

前提准备 项目前端代码和效果 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"…

C语言——枚举类型

&#x1f4dd;前言&#xff1a; 在之前的文章中我们已经讲解了自定义类型中的结构体类型和联合体类型&#xff0c;现在我们再充分学习一下C语言中的枚举类型&#xff1a; 1&#xff0c;什么是枚举类型 2&#xff0c;枚举类型的定义和变量的声明 3&#xff0c;对变量进行赋值 &a…

455. Assign Cookies(分发饼干)

题目描述 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#xff0c;都有一个…

OpenCompass 大模型评测

在浦语的大模型评测教程课程中&#xff0c;你可能需要完成的任务包括&#xff1a; 先修知识准备&#xff1a;这里你需要理解并掌握深度学习、NLP和PyTorch等相关知识。因为这些都是进行大模型评测的基础。模型理解&#xff1a;你需要对你要评测的模型有一个全面的理解&#xf…