【带头学C++】----- 三、指针章 ---- 3.11 补充重要指针知识

news2024/11/17 23:49:05

1.指针的指针(多级指针)

        指针的指针(Pointer to Pointer)是指一个指向指针的指针变量。也就是说,它存储了一个指向指针的内存地址。在C++中,指针的指针可以用来传递多个指针参数,或者用于在函数内部动态分配内存,以及实现其他高级的指针应用。

指针的指针的一般形式如下:

datatype** pointer_name;

其中,datatype 是指针所指向的数据类型,pointer_name 是指向指针的指针变量的名称。

指针的指针可以使用以下方式进行声明和初始化:

int x = 10;
int* ptr = &x;
int** ptr_ptr = &ptr;

      在上面的示例中,我们首先定义了一个整型变量 x,并将其赋值为10。然后,我们声明了一个整型指针 ptr,并将其初始化为 x 的地址。最后,我们声明了一个指向指针的指针变量 ptr_ptr,将其初始化为指向 ptr 的地址。

     我们可以使用解引用运算符 * 和指针运算符 & 来访问和操作指针的指针。例如,以下代码演示了如何使用指针的指针来访问 x 变量的值:

std::cout << "x 的值为:" << **ptr_ptr << std::endl;

在上面的代码中,我们使用两个星号 ** 来解除指针的指针,并得到所指向的值。输出结果为:

x 的值为:10

指针的指针还可以用于函数参数传递,特别是在需要动态创建多个指针变量时。例如,可以使用指针的指针在函数内部动态创建二维数组:

void allocate(int**& arr, int row, int col) {
    arr = new int*[row];
    for (int i = 0; i < row; i++) {
        arr[i] = new int[col];
    }
}

int main() {
    int** arr;
    int row = 3, col = 4;
    allocate(arr, row, col);
    // 使用二维数组
    // ...
}

在上面的代码中,我们定义了一个指针的指针变量 arr,并将其传递给 allocate 函数。该函数使用指针的指针动态创建了一个二维数组,并将其赋值给 arr,以便在主函数中使用。

注意:n级指针变量可以保存 n-1级指针变量的地址

 

       上面的实例里面我们想通过二级指针**q,来访问第0级也就是num的值,第一次*q时我们取到的值是一级指针变量p的地址,一级指针又指向了num(处于第0级,最底下的一级)。 注意:前提是一定要建立多级的指向的关系,如果没有指向的关系,则取多级指针也是非法的,不合理的。容易导致内存泄露或者空指针现象。

2.数组的指针(前面讲过数组指针指针数组

1.数组首元素的地址和数组首地址的概念 

数组指针是指向数组的指针变量,可以通过指针运算和索引运算来访问和操作数组。

1.数组首元素地址 (非指针使用的普通一维数组,二维的需要另外再说)

       数组首元素的地址指的是数组中第一个元素的内存地址。在C++中,数组名本身就表示数组的首地址,因此可以将数组名视为指向数组首元素的指针。

例如:

int arr[5] = {10,20,30,40,50};
cout<<"arr"<<arr<<endl;//此时跳过一个元素大小的字节长度
cout<<"arr+1"<<arr+1<<endl;

2.数组首地址:

       数组首地址是指数组中第一个元素的内存地址。在C++中,数组名本身就指向数组的首地址。可以通过数组名来访问和操作数组的元素。

例如:

//arr数组元素的地址 +1 跳过一个元素
//&arr[0] +1  

int arr[5] = {10,20,30,40,50};
cout<<"arr"<<arr<<endl;//此时+1以后会跳过一个数组大小长度
cout<<"arr+1"<<arr+1<<endl;

2.数组指针的本质

   数组指针本质是指针变量,保存的是数组的首地址

例如:

int (*p)[5] = NULL; //数组指针,*p看作一个整体,从右往左读
//它声明了一个指针变量 p,该指针指向一个包含 5 个 int 元素的数组。
//(*p) 表示指针 p 所指向的值(即指向的数组)。
//而 [5] 表示该数组的大小为 5。
//因此,int (*p)[5] 表示 p 是一个指向包含 5 个 int 元素的数组的指针。
int *p[5] = NUll; //指针数组    此时是  int  *  p[5]  左往右读 指针数组,
/*
[]优先级高,所有p先和[]结合

p:表示一个 数组(即数组名)
这个数组包含了 5 个元素,每一个元素都是一个 int * 类型的指针。

*p:表示这个数组中一个元素所指向的值(即指针所指向的变量),
这个值是一个 int 类型的变量。
*/

在下例中,数组 arr 的类型是 int[5],所以偏移量将会是 5 * sizeof(int),即 20 字节(假设 sizeof(int) 为 4 字节)。

因此,p+1 将会指向一个以 arr 数组大小为单位偏移的位置,即 &arr + 1。这相当于跳过了一个 arr 数组的大小。

 

       上述数组指针可能会导致未定义行为,所以增加对arr数组的一个引用。并且引用的规则也是必须要求数组的大小和类型是匹配的,一致的。

 下图示中,展示如何通过指针变量取访问数组的值,或者说是获取数组的某个元素的地址,达到我们操控数组的值的目的。

指针数组相当于是二维数组里面的一维数组, 最后可以转化为二维数组去表示,p[0][2]

指针数组案例分析:

    int arr[5] = {10,20,30,40,50};
    int (*p)[5] = &arr;
    cout << *((int *)(p+1)-2) <<endl; //40分析为啥是40

 解析:

        首先, (p+1) 表示指针 p 偏移了一个 arr 数组的大小,即指向了 arr 数组后面的一个数组。由于 p 是指向 int[5] 类型的数组指针,因此,这个偏移量是 5 * sizeof(int),即 20 字节。

        然后,(int *)(p+1) 将 (p+1) 的结果强制转换为 int* 类型指针。这时,编译器会将这个指针解释为以 int 类型为单位的偏移量。

        最后,最外层的 *((int *)(p+1)-2) 表示取出 (p+1) 指向的位置往前偏移 2 个 int 单位的值。由于 arr 是一个 int[5] 类型的数组,每个 int 单位占用 4 字节,所以往前偏移 2 个 int 单位就是往前偏移了 (2*4) = 8 字节,即 20 - 8 = 12 字节。也就是说,这个表达式的结果指向了 &arr[3] 的位置,对应的值为 arr[3] 的值,即 40

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

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

相关文章

期中成绩发布啦

期中考试过后&#xff0c;老师们最头疼的事情之一就是成绩的录入和发布。而学生们最关心的事情之一则是如何能够快速、方便地查询到自己的成绩。那么&#xff0c;如何让学生自主查询成绩呢&#xff1f;下面就给大家介绍几种简单实用的方法。 一、使用学校官网或教务系统查询 现…

1698 - Access denied for user ‘root‘@‘192.168.229.1‘

目录 1. 问题现象 2. 问题分析及解决方法 1. 问题现象 在使用mysql连接工具连接mysql的时候如下&#xff1a; 出现了如下错误&#xff1a; 2. 问题分析及解决方法 出现这种错误一般有两种情况&#xff1a;一种是密码输入错误&#xff0c;重新检查一下密码再试一下&#xf…

后期混音效果全套插件Waves 14 Complete mac中文版新增功能

Waves 14 Complete for Mac是一款后期混音效果全套插件&#xff0c;Waves音频插件,内置混响&#xff0c;压缩&#xff0c;降噪和EQ等要素到建模的模拟硬件&#xff0c;环绕声和后期制作工具&#xff0c;包含全套音频效果器&#xff0c;是可以让你使用所有功能。Waves 14 Comple…

简述SVM

概述 SVM&#xff0c;即支持向量机&#xff08;Support Vector Machine&#xff09;&#xff0c;是一种常见的监督学习算法&#xff0c;用于分类和回归问题。它是一种基于统计学习理论和结构风险最小化原则的机器学习方法。 SVM的主要思想是在特征空间中找到一个最优的超平面…

智慧农业:农林牧数据可视化监控平台

数字农业是一种现代农业方式&#xff0c;它将信息作为农业生产的重要元素&#xff0c;并利用现代信息技术进行农业生产过程的实时可视化、数字化设计和信息化管理。能将信息技术与农业生产的各个环节有机融合&#xff0c;对于改造传统农业和改变农业生产方式具有重要意义。 图扑…

AVL平衡树的插入

//AVL搜索树 //对数据的搜索&#xff1a; 1&#xff1a;暴力查找遍历 // 2:二叉树 有序&#xff0c;但是伴随着插入删除&#xff0c;维护成本很高 // 3&#xff1a;二叉搜索树 问题&#xff1a;在极端情况下&#xff0c;会退化成最开始的链表 // …

inne所属公司抢注“童年时光”商标仍被冻结

根据中国商标网查询&#xff0c;国家知识产权局已于2023年3月10日裁定&#xff0c;被告inne所属的南京童年时光生物技术有限公司注册的“童年时光”商标无效。随着这起保健品行业品牌资产争夺事件的发酵&#xff0c;更多的细节得到披露&#xff0c;至此&#xff0c;一个从“代理…

低代码+RPA,会发生什么?

据相关研究表明&#xff0c;每个企业员工每天至少花1-2个小时完成文件归档、数据输入等工作&#xff0c;而这些工作都是可以通过自动化的方式完成的。 如今&#xff0c;不少企业正专注于工作流程自动化&#xff0c;希望能花最少的时间完成重复性工作&#xff0c;机器人流程自动…

Python基础入门(17)----Python虚拟环境:为何要用虚拟环境、如何使用virtualenv

文章目录 在Python开发中,虚拟环境是一个独立的目录树,可以在其中安装Python模块。每个虚拟环境都有自己的Python二进制文件和一组安装的库。使用虚拟环境的主要原因是为了避免项目间的依赖冲突,允许每个项目有其特定的依赖,而不影响全局安装的模块。 为何要用虚拟环境 依…

Vue 最简单路由 页面路由 配置路由

路由安装 Vue3使用 vue-router4 Vue2使用 vue-router3 npm i vue-router3创建路由文件 配置路由规则 import Vue from vue import VueRouter from vue-router //导入路由器 Vue.use(VueRouter)import Login from ../components/Login import User from ../components/User //…

17、Python虚拟环境:为何要用虚拟环境、如何使用virtualenv

文章目录 在Python开发中,虚拟环境是一个独立的目录树,可以在其中安装Python模块。每个虚拟环境都有自己的Python二进制文件和一组安装的库。使用虚拟环境的主要原因是为了避免项目间的依赖冲突,允许每个项目有其特定的依赖,而不影响全局安装的模块。 为何要用虚拟环境 依…

Linux 进程的管道通信

文章目录 无名管道pipe有名管道 进程之间的通信&#xff1a;Linux环境下&#xff0c;进程地址空间相互独立&#xff0c;每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另外一个进程中都看不到&#xff0c;所以进程之间不能相互访问&#xff0c;要交换数据必须通过…

分享68个毕业答辩PPT,总有一款适合您

分享68个毕业答辩PPT&#xff0c;总有一款适合您 链接&#xff1a;https://pan.baidu.com/s/1trwZ8T2I2rFh59LVxTSXTw?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。知识付费甚欢…

开源DB-GPT实现连接数据库详细步骤

官方文档&#xff1a;欢迎来到DB-GPT中文文档 — DB-GPT &#x1f44f;&#x1f44f; 0.4.1 第一步&#xff1a;安装Minicoda https://docs.conda.io/en/latest/miniconda.html 第二步&#xff1a;安装Git Git - Downloading Package 第三步&#xff1a;安装embedding 模型到…

TFTP协议详解

1.简介 TFTP&#xff08;Trivial File Transfer Protocol,简单文件传输协议&#xff09;是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议&#xff0c;提供不复杂、开销不大的文件传输服务。端口号为69。 FTP是一个传输文件的简单协议&#xff0c;它基…

亚马逊怎么下单更真实

亚马逊是一个知名的在线购物平台&#xff0c;为了下单更真实&#xff0c;可以采取以下步骤&#xff1a; 1、查看商品信息&#xff1a;在浏览亚马逊的商品时&#xff0c;仔细查看商品描述、照片和客户评价。这些信息可以帮助你了解产品的真实情况。 2、对比价格&#xff1a;比…

Android Studio(项目打包成APK)

打包流程 直接上图即可 按照上面操作后&#xff0c;即可以开始打包&#xff0c;一般第一次打包都需要几分钟&#xff08;我第一次打包花了七八分钟&#xff09;&#xff0c;如果打包错误了也别担心&#xff0c;可以查看错误分析一下原因&#xff0c;实在不行可以把错误放到网站…

macos端串口调试推荐 serial直装激活 for mac

serial for mac版软件特色 1.准备好macOS High Sierra 最近的升级是否会让您的设备落后&#xff1f;Serial将使其恢复正常工作&#xff0c;同时保持Mac的安全功能完好无损。 2.完美无瑕的仿真 Serial是一个全功能的终端仿真器&#xff0c;支持Xterm&#xff0c;VT102和ANSI…

软件测试/测试开发丨PyCharm安装指南与技巧分享

点此获取更多相关资料 PyCharm 简介 工欲善其事&#xff0c;必先利其器。为了良好的学习体验&#xff0c;我们需要一款功能全面&#xff0c;并且容易上手的代码编辑器&#xff0c;那么首选大名鼎鼎的 PyCharm。 PyCharm 是一款功能强大的 Python 集成化开发工具&#xff0c;…

Linux系统CH347应用—GPIO输出输入与中断功能

Linux/安卓系统可使用CH347转接GPIO功能&#xff0c;所有GPIO均为双向IO口&#xff0c;支持输出与输入切换&#xff0c;输出时为推挽输出结构&#xff0c;具有较强驱动能力&#xff0c;输入时内部为弱上拉输入&#xff0c;上拉能力较弱。此外&#xff0c;用作输入的GPIO还支持G…