二维数组与指针的关系详解

article/2025/8/21 20:54:54

静态二维数组与指针

我们定义一个二维数组int a[4][3]。

二维数组实际是由多个一维数组组成,在这里,a[3][4]就是由3个长度为4的一维数组组成的二维数组。并且它们在空间上是连续的,相当于一个长为12的一维数组。

这里a,a[i]全部为指针,a为指向整个数组第一个一维数组的指针,a+1指向第二个一维数组,a[0]则指向第一个一维数组的第一个元素,a[1]指向第二个一维数组的第一个元素。

类型说明

 

a的类型为int(*)[4],数组指针(后面动态数组还会出现指针数组,注意区别),是指向第一个一维数组的指针,即a所指向的类型为一个一维数组。

a[0]的类型为int*,是指向第一个一维数组第一个元素的指针,即a[0]指向的类型为一个元素,这里是int。

数组与指针的关系

要弄清楚数组与指针的关系,我们需要弄清楚*a,a,&a,a[0],a[0][0]之间的关系。

首先我们来看一下它们的值。a[0][0]自然不用说,就是数组第一个值。

剩下的我们来猜一猜值:

        std::cout << *a << std::endl;std::cout << &a << std::endl;std::cout << a << std::endl;std::cout << a[0] << std::endl;std::cout << &a[0] << std::endl;

它们输出的值都相同,都是同一个地址。

那它们之间有什么差异呢。这里我们使用+1来判断。

首先我们要知道,一个指针+1就是指针向后移动它所指向类型的字节数。假如指向的是int类型,就会向后移动4位(不同环境int字节可能不同),如果指向的是一个长为4的int类型的数组,将会后移4×4=16位。这里的位是指地址的位,地址是以字节位单位编号的,所以地址里的的每一个数就对应一个字节的数据。

我们从新重新使用以下代码:

	std::cout <<"a:\t\t" <<a << std::endl;//没+1前都一样所以其他的省略std::cout << "*a+1:\t\t"<<*a+1 << std::endl;std::cout << "&a+1:\t\t"<<&a + 1 << std::endl;std::cout << "a+1:\t\t"<<a + 1 << std::endl;std::cout << "a[0]+1:\t\t"<<a[0] + 1 << std::endl;std::cout << "&a[0] + 1:\t"<<&a[0] + 1 << std::endl;	std::cout << "&a[0][0] + 1:\t"<<&a[0][0] + 1 << std::endl;

结果如下:

我们发现

*a+1和a[0]+1,&a[0][0]一样,移动了4位(变大了4)。因为它们本质上来说是一样的。a指向第一个一维数组,也就指向a[0],a[0]指向第一个数组的第一个元素,也就是指向a[0][0]。

&a+1指针后移了48位,因为它指向的是a[3][4]这个数组,这里int型数据占4个字节,+1则后移3×4×4位。

a+1 指针后移了16位,因为它指向的是第一个[4]的一维数组,即a[0],+1后移4×4位。

&a[0]等同于a,因为a就是a[3][4]中第一个数组的地址。

元素的获取

要获得数组的元素,m行n列元素,可以用三种方法。

1.直接用下标访问:a[m][n];

2.用第m行指针位移:*(a[m]+n);

3.用第一个元素位移:*(*(a+m)+n);

长度计算

 从上面我们可以知道,a,a[0]这些都是地址,那么它们的长度是多少呢。

int a[3][4];	
std::cout << sizeof(a[0]) << std::endl;
std::cout << sizeof(a) << std::endl;

结果为 16 48。分别为一维数组长度和二维数组长度。但是这里就有疑问了,它们不是指针吗,它们的长度不该是指针本身的长度吗,这是因为编译器在将 C 代码转换成汇编代码时,自动将其替换成了实际的数值。但是它们如果作参数传入函数里,则只会传入指针,比如运行以下代码:

void test(int b[3][4]) {std::cout << sizeof(b) << std::endl;
}int main()
{int a[3][4];test(a);
}

这时候我们会得到a的长度为4(x86)或8(x64)

这个时候指针b的长度就为指针本身的长度。因为b本来就是指针,我们经常在数组作参数传入函数时,会多加一个参数记录其长度一样,因为数组指针并没有整个数组的长度信息,只能将首地址传入函数。

如果没搞清楚可以看我的另一篇博客:点这里。

动态二维数组与指针

这里我们只讨论new这种方式创建的二维数组。

int** a = new int*[3];//创建3×4的数组for (int i = 0; i < 3; i++){a[i] = new int[4];}

其存储结构如下:

这里可以看到new创建的动态二维数组也是由多个一维数组组成的。不同的是,动态二维数组的中这些一维数组并没有相连,而是每个数组对应一个指向其第一个数的指针。再将这些指针组合成数组(静态数组没有这个指针数组)。a就是指向这些数组指针组成的数组的第一个数的地址。之所以有空白是因为动态数组长度可以增加,并没有静态数组那样的限制,因此声明时数组的长度可以是参数。

注意:指针数组长度可以增加,指针数组每一个指针对应的一维数组可以增加,并不代表二维数组x,y坐标没有限制,比如上面数组就不能给a[3][1]赋值,一维就是有了a[3]这个指针,也没有对其指向的数组声明,即没有a[3] = new int[4]这样一个过程。

我们用之前的代码测试:

	std::cout << a << std::endl;std::cout << a[0] << std::endl;std::cout << &a[0] << std::endl;std::cout << &a[0][0] << std::endl;

得到如下结构: 

从结果中我们发现,和静态二维数组不一样,a和a[0]的值不同。因为a[0]指向第一个一维数组的指针,a为指向指针构成的数组的第一个元素的指针。a的类型为int**,a[0]的类型为int*。这里a和a[0]都是指向的一维数组,只不过a[0]指向的元素是int,a指向的元素是指针。

+1后结果如下(代码中数组用的c表示,这里和a不加区别):

可以看到,无论是c还是c[0],+1后都是移动4位,因为它们都是指向一维数组第一个元素的指针,元素类型分别为指针类型和int类型,int类型占4个字节,指针类型也占4个字节。*c=c[0]因为c指向的是指针数组的第一个位置。

虽然在地址+1操作做动态二维数组和静态二维数组所得到的地址值变换不一样,但是所对应到数组的值都一样。所以上面这些计算元素的方法,动态数组和静态数组所得结果都是一样的。

要获得数组的元素,m行n列元素,可以用三种方法。

1.直接用下标访问:a[m][n];

2.用第m行指针位移:*(a[m]+n);

3.用第一个元素位移:*(*(a+m)+n);

半截子动态二维数组

这里稍微介绍一下,并不常用

int(*array)[3] = new int[4][3];

 

它的存储结构和静态数组很像,因为列是静态的,所以还是一维的存储方式,不同的是它还能对a[4][2],a[5][1]等元素进行操作,因为它的行是动态的。

 为什么我把它叫半截子的动态二维数组?因为它只有行具有动态功能。

还有个有趣的地方就是,比如a[0][4]这个元素,列超出了范围,会向下一行继续移动,即a[0][2]向后移动两位,也就是说它完全等于      a[1][1],地址一样,就是同一个数

 

如有错误,还望指正。


http://chatgpt.dhexx.cn/article/FfoPmfFN.shtml

相关文章

二维数组与指针(详解)

如果对字符串和二维数组有基本概念可以直接跳去看他们的关系及使用 于4.3 00:08修改&#xff0c;改正了之前文章中错误的观点&#xff0c;修改了一些低级错误 欢迎大家在文章下留言 于21-05-19 22:37再次更新,前几天有个同学问了我这么个问题&#xff0c;我觉得是一个非常好的…

C/C++二维数组指针(指向二维数组的指针)详解

多维数组与指针 用指针变量可以指向一维数组中的元素&#xff0c;也可以指向多维数组中的元素。1) 多维数组元素的地址 设有一个二维数组 a&#xff0c;它有 3 行 4 列。它的定义为&#xff1a; int a[3][4]{{1,3,5,7},{9,11,13,15},{17,18,21,23}}; a 是一个数组名。a 数…

C语言 指针+二维数组详解 (应付期末、考研的最强笔记,建议收藏)

哈喽&#xff01;这里是一只派大鑫&#xff0c;不是派大星。本着基础不牢&#xff0c;地动山摇的学习态度&#xff0c;从基础的C语言语法讲到算法再到更高级的语法及框架的学习。更好地让同样热爱编程(或是应付期末考试 狗头.jpg)的大家能够在学习阶段找到好的方法、路线&#…

多任务Multitask Learning

一次只学习一个任务&#xff0c;大部分机器学习都属于单任务学习。 多任务学习&#xff1a;把多个相关的任务放在一起学习&#xff0c;同时学习多个任务。 对于复杂的问题&#xff0c;可以分解为简单的相互独立的子问题来解决&#xff0c;然后再合并结果&#xff0c;得到最初复…

Distral: Robust multitask reinforcement learning.

作者&#xff1a;张楚珩 链接&#xff1a;https://zhuanlan.zhihu.com/p/51091244 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 中Distral是Distill & transfer learning的缩写。 原文传送门 Teh, Yee, et…

论文阅读笔记--Clustered Federated Learning:Model-Agnostic Distributed Multitask Optimization Under Privacy

Introduction 传统的Parameter Server&#xff08;P-S&#xff09;架构的联邦学习系统尝试训练出一个模型&#xff0c;让它能适用于每一个client的数据分布&#xff0c;这暗含了一个假设&#xff0c;模型的最优解 θ ∗ \theta^* θ∗同时是所有client的最优解&#xff0c;各个…

CVPR 2021 UniT: Multimodal Multitask Learning with a Unifified Transformer

动机 transformer在包括但不限于自然语言、图像、视频和音频在内的广泛领域都显示出巨大的成功。 前人的研究表明,在大型语料库中训练的transformer在一系列的下游语言任务中学习了强大的表征。在视觉领域中,基于transformer的模型在图像分类、目标检测和全景分割方面取得了非…

Language Models are Unsupervised Multitask Learners 笔记

语言模型是无监督的多任务学习者 摘要 自然语言处理任务&#xff0c;如问题回答、机器翻译、阅读理解和总结&#xff0c;通常是通过任务特定数据集上的监督学习来完成的。我们证明&#xff0c;当语言模型在一个称为WebText的数百万网页的新数据集上训练时&#xff0c;它们可以…

GPT2.0 Language Models are Unsupervised Multitask Learners 论文解读

转载请注明出处&#xff0c;原文地址 本文是对《Language Models are Unsupervised Multitask Learners》的翻译&#xff0c;部分内容可能会存在理解错误&#xff0c;如有错误欢迎指正交流。 个人对论文的理解 最近GPT-2的关注度很高&#xff0c;其效果极其惊人&#xff0c;…

【论文阅读】强化学习-Transfer and Multitask RL专题8篇

文章目录 什么是Transfer and Multitask RLProgressive Neural Networks, Rusu, et al, 2016. Algorithm: Progressive Networks.Universal Value Function Approximators, Schaul et al, 2015. Algorithm: UVFA.Reinforcement Learning with Unsupervised Auxiliary Tasks, Ja…

论文阅读 decaNLP -- The Natural Language Decathlon: Multitask Leaning as Question Answering

作为一个刚刚入门NLP的学生&#xff0c;希望在阅读每一篇论文后都进行一定的记录&#xff0c;提炼文中观点&#xff0c;写出自己的理解&#xff0c;如有任何解读错误之处敬请指出&#xff0c;&#xff2f;&#xff08;∩&#xff3f;∩&#xff09;&#xff2f;谢谢&#xff01…

Recommending What Video to Watch Next: A Multitask Ranking System

文章目录 总结细节实验 总结 魔改mmoewide&deep 细节 mmoewide&deep 分成2个阶段&#xff1a;获得candidates、ranking&#xff0c;ranking时用point-wise ranking时&#xff0c;用w&d获取浅层feature&#xff0c;用于移除position bias ranking model&#x…

《BDD100K: A Diverse Driving Dataset for Heterogeneous Multitask Learning》论文阅读笔记

论文链接 A Diverse Driving Dataset for Heterogeneous Multitask Learning Abstract 介绍了BDD100K数据集&#xff0c;包含100K段视频以及10种类型的任务&#xff0c;针对这种多元化任务需要特殊的训练策略。 1 Introduction ImageNet、COCO等数据集在之前很长一段时间里…

multitask-graph-attention(一)

多任务图注意力框架预测药物毒性&#xff0c;原文&#xff1a;Mining Toxicity Information from Large Amounts of Toxicity Data&#xff0c;代码&#xff1a;MGA&#xff0c;文章从 MGA/interpretation/Ames_interpret.ipynb 开始 文章目录 1.build_dataset1.1.load_graph_…

12.UniT:Multimodal Multitask Learning with a Unified Transformer

1.动机 UniT&#xff0c;它通过统一transformer联合学习跨不同领域的多个任务。我们的UniT模型可以同时处理8个数据集上的7个任务&#xff0c;从对象检测到视觉和语言推理以及自然语言理解&#xff0c;同时通过紧凑的模型参数集实现每个任务的强大性能。 我们提出了一个统一的t…

Flow Prediction in Spatio-Temporal Networks Based on Multitask Deep Learning(TKDE2020)

Flow Prediction in Spatio-Temporal Networks Based on Multitask Deep Learning&#xff08;TKDE2020&#xff09; 摘要&#xff1a;预测交通流(如车辆、人群和自行车的交通)&#xff0c;包括在一个节点的进出交通和不同节点之间的过渡&#xff0c;在交通运输系统的时空网络…

GPT2.0语言模型 Language Models are Unsupervised Multitask Learners

论文链接&#xff1a;https://d4mucfpksywv.cloudfront.net/better-language-models/language-models.pdf Tensorflow代码链接&#xff1a;https://github.com/openai/gpt-2 Pytorch代码链接&#xff1a;https://github.com/huggingface/pytorch-pretrained-BERT 参考文档&…

论文阅读《Language Models are Unsupervised Multitask Learners》

论文地址&#xff1a;《Language Models are Unsupervised Multitask Learners》 代码地址&#xff1a;https://github.com/openai/gpt-2 文章目录 论文介绍模型框架实验分析结论 论文介绍 本文将常识推理和情感分析两项任务联系起来&#xff0c;采取更一般的方法。证明了语言…

MulT: An End-to-End Multitask Learning Transformer 多任务共享注意力

文章 同时学习多个高级视觉任务&#xff0c;包括深度估计、语义分割、reshading表面法线估计、2D 关键点检测和边缘检测。 与单个任务Transformer相比&#xff0c;跨任务联合培训的Transformer模型能否提高每个任务的性能&#xff1f;在基于Transformer的框架中&#xff0c;可…

Paper | Multitask learning

目录 1. MTL的定义2. MTL的机制 2.1. Representation Bias2.2. Uncorrelated Tasks May Help&#xff1f;3. MTL的用途 3.1. Using the Future to Predict the Present3.2. Time Series Prediction3.3. Using Extra Tasks to Focus Attention3.4. Quantization Smoothing3.5. S…