二维数组指针表示,C语言指针引用二维数组详解

article/2025/8/21 21:04:04

指针变量可以指向一维数组中的元素,当然也就可以指向二维数组中的元素。但是在概念和使用方法上,二维数组的指针比一维数组的指针要复杂一些。要理解指针和二维数组的关系首先要记住一句话:二维数组就是一维数组,这句话该怎么理解呢?

假如有一个二维数组:

int a[3][4] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}};

其中,a 是二维数组名。a 数组包含 3 行,即 3 个行元素:a[0],a[1],a[2]。每个行元素都可以看成含有 4 个元素的一维数组。而且 C 语言规定,a[0]、a[1]、a[2]分别是这三个一维数组的数组名。如下所示:

在这里插入图片描述

a[0]、a[1]、a[2] 既然是一维数组名,一维数组的数组名表示的就是数组第一个元素的地址,所以 a[0] 表示的就是元素 a[0][0] 的地址,即 a[0] == &a[0][0];a[1] 表示的就是元素 a[1][0] 的地址,即 a[1] == &a[1][0];a[2] 表示的就是元素 a[2][0] 的地址,即 a[2] == &a[2][0]。

所以二维数组a[M][N]中,a[i]表示的就是元素a[i][0]的地址,即(式一):

a[i] == &a[i][0]

我们知道,在一维数组 b 中,数组名 b 代表数组的首地址,即数组第一个元素的地址,b+1 代表数组第二个元素的地址,…,b+n 代表数组第 n+1 个元素的地址。所以既然 a[0]、a[1]、a[2]、…、a[M–1] 分别表示二维数组 a[M][N] 第 0 行、第 1 行、第 2 行、…、第 M–1 行各一维数组的首地址,那么同样的道理,a[0]+1 就表示元素 a[0][1] 的地址,a[0]+2 就表示元素 a[0][2] 的地址,a[1]+1 就表示元素 a[1][1] 的地址,a[1]+2 就表示元素 a[1][2] 的地址……a[i]+j 就表示 a[i][j] 的地址,即(式二):

a[i]+j == &a[i][j]

将式一代入式二得(式三):

&a[i][0]+j == &a[i][j]

在一维数组中 a[i] 和 *(a+i) 等价,即(式四):

a[i] == *(a+i)(13-4)

这个关系在二维数组中同样适用,二维数组 a[M][N] 就是有 M 个元素 a[0]、a[1]、…、a[M–1] 的一维数组。将式四代入式二得(式五):

*(a+i)+j == &a[i][j]

由式二和式五可知,a[i]+j 和 *(a+i)+j 等价,都表示元素 a[i][j] 的地址。

上面几个公式很“绕”,理清楚了也很简单,关键是把式二和式五记住。


二维数组的首地址和数组名

下面来探讨一个问题:“二维数组 a[M][N] 的数组名 a 表示的是谁的地址?”在一维数组中,数组名表示的是数组第一个元素的地址,那么二维数组呢? a 表示的是元素 a[0][0] 的地址吗?不是!我们说过,二维数组就是一维数组,二维数组 a[3][4] 就是有三个元素 a[0]、a[1]、a[2] 的一维数组,所以数组 a 的第一个元素不是 a[0][0],而是 a[0],所以数组名 a 表示的不是元素 a[0][0] 的地址,而是 a[0] 的地址,即:

a == &a[0]

而 a[0] 又是 a[0][0] 的地址,即:

a[0] == &a[0][0]

所以二维数组名 a 和元素 a[0][0] 的关系是:

a == &(&a[0][0])

即二维数组名 a 是地址的地址,必须两次取值才可以取出数组中存储的数据。对于二维数组 a[M][N],数组名 a 的类型为 int(*)[N],所以如果定义了一个指针变量 p:

int *p;

并希望这个指针变量指向二维数组 a,那么不能把 a 赋给 p,因为它们的类型不一样。要么把 &a[0][0] 赋给 p,要么把 a[0] 赋给 p,要么把 *a 赋给 p。前两个好理解,可为什么可以把 *a 赋给 p?因为 a==&(&a[0][0]),所以 a==(&(&a[0][0]))==&a[0][0]。

除此之外你也可以把指针变量 p 定义成 int(*)[N] 型,这时就可以把 a 赋给 p,而且用这种方法的人还比较多,但我不喜欢,因为我觉得这样定义看起来很别扭。

如果将二维数组名 a 赋给指针变量 p,则有(式六):

p == a

那么此时如何用 p 指向元素 a[i][j]?答案是以“行”为单位进行访问。数组名 a 代表第一个元素 a[0] 的地址,则 a+1 就代表元素 a[1] 的地址,即a+1==&a[1];a+2 就代表 a[2] 的地址,即 a+2==&a[2]……a+i 就代表 a[i] 的地址,即(式七):

a+i == &a[i]

将式六代入式七得:

p+i == &a[i]

等式两边作“*”运算得:

*(p+i) == a[i]

等式两边同时加上j行(式八):

*(p+i) + j == &a[i][j]

式八就是把二维数组名 a 赋给指针变量 p 时,p 访问二维数组元素的公式。使用时,必须先把 p 定义成 int()[N] 型,然后才能把二维数组名 a 赋给 p。那么怎么把 p 定义成 int()[N] 型呢?关键是 p 放什么位置!形式如下:

> int (*p)[N] = a;    /*其中N是二维数组a[M][N]的列数, 是一个数字, 前面说过, 数组长度不能定义成变量*/

下面编一个程序来用一下:

# include <stdio.h>
int main(void)
{int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};int i, j;int (*p)[4] = a;  //记住这种定义格式for (i=0; i<3; ++i){for (j=0; j<4; ++j){printf("%-2d\x20", *(*(p+i)+j));  /*%-2d中, '-'表示左对齐, 如果不写'-'则默认表示右对齐;2表示这个元素输出时占两个空格的空间*/}printf("\n");}return 0;
}

输出结果是:

1  2  3  4
5  6  7  8
9  10 11 12

如果把 &a[0][0] 赋给指针变量 p 的话,那么如何用 p 指向元素 a[i][j] 呢?在前面讲过,对于内存而言,并不存在多维数组,因为内存是一维的,内存里面不分行也不分列,元素都是按顺序一个一个往后排的,所以二维数组中的每一个元素在内存中的地址都是连续的,写一个程序来验证一下:

# include <stdio.h>
int main(void)
{int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};int i, j;for (i=0; i<3; ++i){for (j=0; j<4; ++j){printf("%#X\x20", &a[i][j]);}printf("\n");}return 0;
}

输出结果是:

0X18FF18 0X18FF1C 0X18FF20 0X18FF24
0X18FF28 0X18FF2C 0X18FF30 0X18FF34
0X18FF38 0X18FF3C 0X18FF40 0X18FF44

我们看到地址都是连续的。所以对于数组 a[3][4],如果把 &a[0][0] 赋给指针变量 p 的话,那么:

p == &a[0][0]; p + 1 == &a[0][1]; p + 2 == &a[0][2]; p + 3 ==
&a[0][3]; p + 4 == &a[1][0]; p + 5 == &a[1][1]; p + 6 == &a[1][2];
p + 7 == &a[1][3]; p + 8 == &a[2][0]; p + 9 == &a[2][1]; p + 10
== &a[2][2]; p + 10 == &a[2][3];

如果仔细观察就会发现有如下规律:

p+i*4+j == &a[i][j]

其中 4 是二维数组的列数。

所以对于二维数组 a[M][N],如果将 &a[0][0] 赋给指针变量 p 的话,那么 p 访问二维数组元素 a[i][j] 的公式就是:

p + i*N +j == &a[i][j]

下面把验证式八的程序修改一下,验证一下上式:

# include <stdio.h>
int main(void)
{int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};int i, j;int *p = &a[0][0];  //把a[0][0]的地址赋给指针变量pfor (i=0; i<3; ++i){for (j=0; j<4; ++j){printf("%-2d\x20", *(p+i*4+j));}printf("\n");}return 0;
}

输出结果是:

1  2  3  4
5  6  7  8
9  10 11 12

结果是一样的。两种方法相比,第二种方法更容易接受,因为把 &a[0][0] 赋给指针变量 p 理解起来更容易,而且 p 定义成 int* 型从心理上或从感觉上都更容易接受。


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

相关文章

C语言二维数组指针(指向二维数组的指针)详解

声明&#xff01;本文转载仅为方便学习使用&#xff01; 如有需要&#xff0c;请访问C语言指针数组&#xff08;数组每个元素都是指针&#xff09;详解C语言二维数组指针&#xff08;指向二维数组的指针&#xff09;详解 二维数组在概念上是二维的&#xff0c;有行和列&#x…

c语言 二维数组指针

文章目录 前言一、二维数组指针的定义&#xff1a;二、二维数组指针遍历数组元素&#xff1a;总结 前言 前面我们讲了一维数组指针&#xff0c;今天我们讲一下二维数组指针。 一、二维数组指针的定义&#xff1a; 概述&#xff1a; 二维数组指针的定义就是把一维数组换成二维…

关于二维数组,二维数组指针

最近学习指针&#xff0c;一不小心就掉进了二维数组指针的坑里面&#xff0c;在迷惑了接近一个星期后&#xff0c;我有了以下的总结。&#xff08;希望有大佬看见了能指点指点&#xff0c;我也不知道这么理解到底对不对&#xff0c;虽然我觉得是对的&#xff09; 这是我一开始…

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

静态二维数组与指针 我们定义一个二维数组int a[4][3]。 二维数组实际是由多个一维数组组成&#xff0c;在这里&#xff0c;a[3][4]就是由3个长度为4的一维数组组成的二维数组。并且它们在空间上是连续的&#xff0c;相当于一个长为12的一维数组。 这里a&#xff0c;a[i]全部…

二维数组与指针(详解)

如果对字符串和二维数组有基本概念可以直接跳去看他们的关系及使用 于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;在交通运输系统的时空网络…