C++指针解读(5)-- 指针和数组(多维数组)

相比一维数组,二维数组的概念和相关运算要复杂得多。

1、二维数组的存储及访问

假设有这么一个二维数组:

int arr[3][4] =
{{ 10, 11, 12, 13 },{ 20, 21, 22, 23 },{ 30, 31, 32, 33 } 
};

我们可以把二维数组看成数组的数组:

(1)包含3行:arr[0]、arr[1]、arr[2];

(2)其中每一行是一个1维数组,它包含4个元素。

这里,我们用arr[0]表示第一行的一维数组;用arr[1] 表示第二行的一维数组;用arr[2] 表示第三行的一维数组。

因为在一维数组中,数组名代表首元素地址,所以arr[0]也表示一维数组arr[0]的首地址,即&arr[0][0];

同理,arr[1]表示&arr[1][0],arr[2]表示&arr[2][0]。

一定要记住这个重要的概念:arr[0]表示第一行的一维数组,arr[1]表示一二行的一维数组。依此类推。

后面对二维数组的访问,都是从这个概念开始展开的。因为对二维数组元素的访问,最终还是要转化到对一维数组的访问。

在一维数组中,指针+1就表示下一个数组元素的地址,所以arr[0]+1, arr[0]+2分别表示第2、第3个元素的地址。

现在我们用上面关于二维数组的知识来访问二维数组中的元素:

int main()
{int arr[3][4] ={{ 10, 11, 12, 13 },{ 20, 21, 22, 23 },{ 30, 31, 32, 33 }};printf("%d  %d  %d  %d\n", *arr[0], *(arr[0] + 1), *(arr[0] + 2), *(arr[0] + 3));printf("%d  %d  %d  %d\n", *arr[1], *(arr[1] + 1), *(arr[1] + 2), *(arr[1] + 3));printf("%d  %d  %d  %d\n", *arr[2], *(arr[2] + 1), *(arr[2] + 2), *(arr[2] + 3));return 0;
}

现在我们可以总结下二维数组相关的指针

表示形式

含义

arr

二维数组名,二维数组元素首地址

arr[0], *arr

第0行的一维数组;也代表0行0列元素地址

arr[0] + 1, &arr[0][1]

0行1列元素地址

*arr[0]

0行0列元素的值,即10

*(arr[0] + 1)

0行1列元素的值,即11

2、二维数组的其他访问方式

前面我们讲到arr代表二维数组首元素的地址,因为这个二维数组由3个一维数组组成,所以arr也代表第一个一维数组的首地址。这样,arr+1就表示第二个一维数组的首地址。

我们可以用下面的代码来验证这个结论:

int main()
{int arr[3][4] ={{ 10, 11, 12, 13 },{ 20, 21, 22, 23 },{ 30, 31, 32, 33 }};printf(" %p\n", arr);printf(" %p\n", arr + 1);int gap = (char)(arr + 1) - (char)(arr);printf(" %d\n", gap);return 0;
}

从输出结果看gap是16个字节,1个整型是4个字节,4个数组元素就是16个字节。arr + 1和arr刚好差一个一维数组所占空间的字节。

因为在一维数组中,arr[0]和*(a+0)等价,所以a[1]和*(a+1)等价,a[i]和*(a+i)等价。因此a[0]+1和*(a+0)+1都是&a[0][1]。

这里,再把二维数组相关指针再总结一下:

表示形式

含义

arr

二维数组名;二维数组元素首地址;表示一维数组arr[0]的首地址

arr[0], *arr, *(arr+0)

第0行的一维数组;也代表0行0列元素地址

arr[0] + 1, &arr[0][1], *(arr+0)+1

0行1列元素地址

*arr[0], *(*(arr+0))

0行0列元素的值

*(arr[0] + 1), *(*(arr+0)+1)

0行1列元素的值

arr[1]+2, *(arr+1)+2, &arr[1][2]

1行2列元素的值

二维数组在内存中是线性存储的,即按一维数组的方式存储,先存第1行,再存第2行。所以,我们可以按顺序方式访问二维数组。

int main()
{int arr[3][4] ={{ 10, 11, 12, 13 },{ 20, 21, 22, 23 },{ 30, 31, 32, 33 }};printf(" *arr = %p  ,arr[0] = %p\n", *arr, arr[0]);int* p = *arr;for (int i = 0; i < 12; i++) {printf(" %d ", *(p + i));}return 0;
}

3、指向一维数组的指针

我们知道,指针变量必须包含它所指向的数据的类型信息,比如int *pi表示一个指向int型数据的指针变量。

arr, arr[0]虽然指向的地址相同,但它们俩所代表的含义是不一样的。

arr是第一个一维数组的首地址,所以arr+1就指向下一个一维数组的首地址,指针移动4*4 = 16个字节;而arr[0]是第一行第一列元素的地址,arr[0]+1下一个元素的指针,指针只移动4个字节。

怎么定义一个指向一维数组的指针?

int (*p)[4]

表示一个指向一维数组的指针,这个数组含4个元素。

注意,int (*p)[4]和int *p[4]的含义完全不同。int *p[4]表示一个数组,数组里的元素是int型指针变量。

用一维数组指针的访问二维数组:

int main()
{int arr[3][4] ={{ 10, 11, 12, 13 },{ 20, 21, 22, 23 },{ 30, 31, 32, 33 }};int(*p)[4] = arr;for (int i = 0; i < 4; i++) {printf(" %d ", (*p)[i]);}printf("\n");for (int i = 0; i < 4; i++) {printf(" %d ", *((*p) + i));}return 0;
}

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

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

相关文章

136.只出现一次的数字

136. 只出现一次的数字 - 力扣&#xff08;LeetCode&#xff09; 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且…

Arduino驱动BNO055 10轴绝对定向传感器(惯性测量传感器篇)

目录 1、传感器特性 2、控制器和传感器连线图 3、驱动程序 BNO055是实现智能9轴绝对定向的新型传感器IC,它将整个传感器系统级封装在一起,集成了三轴14位加速度计,三轴16位陀螺仪,三轴地磁传感器和一个自带算法处理的32位微控制器。

在 Elasticsearch 中实现自动完成功能 3:completion suggester

在这篇博文中&#xff0c;我们将讨论 complete suggester - 一种针对自动完成功能进行优化的 suggester&#xff0c;并且被认为比我们迄今为止讨论的方法更快。 Completion suggester 使用称为有限状态转换器的数据结构&#xff0c;该结构类似于 Trie 数据结构&#xff0c;并且…

Net6 用imagesharp 实现跨平台图片处理并存入oss

项目要求&#xff1a;生成电子证书 一、模板文件在OSS中&#xff0c;直接加载 二、向模板文件添加二维码 三、向模板文件添加多行文字 四、生成二维码&#xff0c;存入本地&#xff0c; 五、向模板文件添加二维码 代码实现步骤 一、建立.net 6 API项目&#xff0c;安装N…

启航kp OpenHarmony环境搭建

前提 启航kp OpenHarmony环境搭建 搭建好OpenHarmony环境 未搭建好可以参考OpenHarmony docker环境搭建 安装vscode 下载好启航kp所需的开发包和样例 下载地址 搭建过程 进入正确文件夹 首先要进入 /home/openharmony 目录下&#xff0c;如果没有打开在vsc左上角找到文…

JUC并发编程——JUC并发编程概述及Lock锁(重点)(基于狂神说的学习笔记)

基于bilibili狂神说JUC并发编程视频所做笔记 概述 什么是JUC JUC时java.util工具包中的三个包的简称 java.util.concurrent java.util.concurrent.atomic java.util.concurrent.locks 业务&#xff1a;普通的线程代码中&#xff0c;我们常使用Runnable接口 但Runnable没有返…

百度开放平台第三方代小程序开发,授权事件、消息与事件通知总结

大家好&#xff0c;我是小悟 关于百度开放平台第三方代小程序开发的两个事件接收推送通知&#xff0c;是开放平台代小程序实现业务的重要功能。 授权事件推送和消息与事件推送类型都以event的值判断。 授权事件推送通知 授权事件推送包括&#xff1a;推送票据、授权成功、取…

便携式电加热器上亚马逊加拿大站CSA C22标准如何办理?

便携式电加热器 便携式电加热器是一种由电源供电的可移动设备&#xff0c;旨在为一块小面积区域供热。 便携式电加热器示例 我们的便携式电加热器政策 亚马逊要求所有便携式电加热器均经过检测&#xff0c;并且符合下列特定法规或标准要求&#xff1a; 商品 法规/标准要求 …

深入理解 python 虚拟机:GIL 源码分析——天使还是魔鬼?

深入理解 python 虚拟机&#xff1a;GIL 源码分析——天使还是魔鬼&#xff1f; 在目前的 CPython 当中一直有一个臭名昭著的问题就是 GIL (Global Interpreter Lock )&#xff0c;就是全局解释器锁&#xff0c;他限制了 Python 在多核架构当中的性能&#xff0c;在本篇文章当…

Java SPI(Service Provider Interface)

Java SPI是Java标准库提供的一种服务发现机制&#xff0c;它通过在classpath下约定的META-INF/services目录中&#xff0c;定义接口和其实现类之间的对应关系&#xff0c;从而动态加载目标接口的实现类。 通过一个实际例子来具体看一下 1、定义接口 public interface Animal …

【使用教程】在Ubuntu下PMM60系列一体化伺服电机通过SDO跑循环同步位置模式详解

本教程将指导您在Ubuntu操作系统下使用SDO&#xff08;Service Data Object&#xff09;来配置和控制PMM60系列一体化伺服电机以实现循环同步位置模式。我们将介绍必要的步骤和命令&#xff0c;以确保您能够成功地配置和控制PMM系列一体化伺服电机。 01.准备工作 在正式介绍之…

一种更具破坏力的DDoS放大攻击新模式

近日&#xff0c;内容分发网络&#xff08;CDN&#xff09;运营商Akamai表示&#xff0c;一种使网站快速瘫痪的DDoS放大攻击新方法正在被不法分子所利用。这种方法是通过控制数量巨大的中间设备&#xff08;middlebox&#xff0c;主要是指配置不当的服务器&#xff09;&#xf…

【VR】【Unity】白马VR课堂系列-VR开发核心基础03-项目准备-VR项目设置

【内容】 详细说明 在设置Camera Rig前,我们需要针对VR游戏做一些特别的Project设置。 点击Edit菜单,Project Settings,选中最下方的XR Plugin Management,在右边面板点击Install。 安装完成后,我们需要选中相应安卓平台下的Pico VR套件,关于怎么安装PICO VR插件,请参…

PyCharm运行Nosetests并导出测试报告

1. Pycharm运行Nosetests PyCharm可以使用两种方法&#xff0c;运行Nosetests测试文件&#xff1a; 1) 图形用户界面GUI a) 在PyCharm中&#xff0c;选中测试文件&#xff0c;如Tests/test_demo.py b) 鼠标右键选择Run Nosetests in test_demo.py即可执行测试 注1&#xff…

Python 自定义模块和包设计英语生词本(文件版)

上一篇&#xff1a;Python 自定义包和模块随机生成6位验证码&#xff08;详解版&#xff09;-CSDN博客 紧接上一篇博文&#xff0c;当我们熟练掌握如何自定义模块和包后&#xff0c;就要开始着手运用模块和包设计自己的小程序。这里我以“英语生词本”为例&#xff0c;来看我如…

vue 请求代理 proxy

目录 为什么需要配置代理 什么是同源策略 如何配置代理 请求代理的原理 举例说明 为什么需要配置代理 因为浏览器的同源策略&#xff0c;当向和本地 devServer 服务器不同源的地址发送请求&#xff0c; 会违反浏览器的同源策略&#xff0c;导致发送失败&#xff0c;所以需…

极简c++(4)类的静态成员

静态数据成员 ::是作用域操作符&#xff01; #include<iostream> using namespace std;class Point{private:int x,y;public:point(int x 0,int y 0):x(x),y(y){}~point();int getX(){return x;}int getY(){return x;} }假设需要统计点的个数&#xff0c;考虑添加一个…

【MySQL】聚合查询与分组查询

我们先重建一个test库&#xff0c;在test库里新建一个people表&#xff08;包含序列号&#xff0c;姓名&#xff0c;工资&#xff09;&#xff0c;再往表该表里新增六条数据&#xff1a; mysql> drop database if exists test; Query OK, 1 row affected (0.07 sec)mysql>…

【mfc/VS2022】计图实验:绘图工具设计知识笔记

绘制曲线&#xff08;贝塞尔曲线&#xff09;&#xff1a; 转自&#xff1a;CDC 类 | Microsoft Learn 绘制一条或多条贝塞尔曲线。 BOOL PolyBezier(const POINT* lpPoints,int nCount);参数 lpPoints 指向包含曲线端点和控制点的 POINT 数据结构数组。 nCount 指定 lpPo…

git 如何删除本地分支且并没有完全合并到目标分支中

git 如何删除本地分支且并没有完全合并到目标分支中 确保你当前所在的分支不是dev_welc_share_permission分支&#xff0c;如果是的话&#xff0c;可以执行以下命令切换到其他分支&#xff08;比如master&#xff09;&#xff1a; git checkout master使用以下命令删除dev_s…