C语言二维数组指针用法

article/2025/8/21 21:00:29

目录

题目

背景概念梳理

一维线性

数组指针

指针步长

数组名与指向其的指针变量名等价

数组的初始化与取元素

数组指针转换关系

解题过程

选项A:* (( * prt+1)[2])

选项B:* ( * (p+5))

 选项C:( * prt+1)+2

选项D: * ( * (a+1)+2)

正确答案

整体代码

参考链接


题目

设有以下定义:

int a[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};
int (*prt)[3] = a, *p = a[0];

则以下能够正确表示数组元素a[1][2]的表达式是()

A. * (( * prt+1)[2])
B. * ( * (p+5))
C. ( * prt+1)+2
D. * ( * (a+1)+2)

链接:设有以下定义: a[4][3]={1,2,3,4,5,6__牛客网,来源:牛客网

背景概念梳理

        以本题为例,二维数组a[4][3],所表示的元素排列如下:

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

        a[4][3]可理解为“一个四行三列的数组”,亦可理解为“数组a包含4个数组元素,每个数组元素包含三个整形元素”

一维线性

        内存中,a 的分布是一维线性的,整个数组占用一块连续的内存,C语言中的二维数组是按行排列的,也就是先存放 a[0] 行,再存放 a[1] 行,最后存放 a[2] 行;每行中的 3 个元素也是依次存放。数组 a 为 int 类型,每个元素占用 4 个字节,整个数组共占用 4×(3×4) = 48 个字节。

        C语言允许把一个二维数组分解成多个一维数组来处理。对于数组 a,它可以分解成三个一维数组,即 a[0]、a[1]、a[2]、a[3]。每一个一维数组又包含了 43个元素,例如 a[0] 包含 a[0][0]、a[0][1]、a[0][2]。

数组指针

int (*prt)[3] = a;

        括号中的*表明 prt 是一个指针变量,它指向某数组,这个数组的类型为int [3](即这个数组是一个包含三个元素的数组),这正是 a 所包含的每个一维数组的类型。指针prt指向a的首个一维数组。

指针步长

        prt是一个指向数组的指针,指针的步长取决于其指向的数据变量的大小,prt指向的是一个数组类型为int[3]的数组,那么其数据结构大小为(3*4)=12字节,即prt在当前情况下,步长为12,(prt+1),(prt-1),所指向的数据内存地址,各差12。

数组名与指向其的指针变量名等价

        数组名表示数组的第一个元素的地址,可将其看作是一个指针常量。而这个指针常量所指向的类型与数组元素的类型一致。在本题中,prt作为指向数组a的第一个元素的地址的指针变量名,数组a的数组名"a"亦表示其数组的第一个元素的地址,两个都是指向数组a的第一个元素的地址,故数组名 a 在表达式中也会被转换为和 prt 等价的指针。

数组的初始化与取元素

        以一维数组为例,初始化的时候"[]"中,所填的数值是要给数组分配几个元素的位置;取元素时,“[]”中,所填的数值是要获取那个索引值的元素,数组的索引值都是从零开始的。“[]”中所填的数值,在数组初始化和取元素时所表达的含义完全不一样。

//初始化
int num[5]; //数组 num 中有 5 个元素,每个元素都是 int 型变量,而且它们在内存中的地址是连续分配的 //取元素
int n1 = num[0];//获取num数组的第零个元素
int n2 = num[1];//获取num数组的第一个元素
int n3 = num[2];//获取num数组的第二个元素
int n4 = num[3];//获取num数组的第三个元素
int n5 = num[4];//获取num数组的第四个元素

数组指针转换关系

int a[4][3];
int (*p)[3] = a;//0<=i<=3, 0<=j<=2 
a+i == p+i
a[i] == *(a+i) //a[i]等价于从数组a的首地址向后数第i个元素
a[i] == p[i] == *(a+i) == *(p+i) 
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)

解题过程

        依题,a[1][2]所对应的值是6,按选项逐个分析:

选项A:* (( * prt+1)[2])

*prt表示的是数组a第一个数组元素的地址=数组a的首地址,

(*prt+1)表示数组a中第二个整形元素的地址(在这里prt发生了退化,指向的是数组a中的首个数组元素的首个整形元素,实际运行结果,*prt与(*prt+1)差4字节,可佐证),

(*prt+1)[2]表示数组a第二个整形元素向后跨两个索引的值,

* (( * prt+1)[2])表示数组a第二个整形元素向后跨两个索引的值作为指针变量所指向的变量,

int main()
{int a[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};int (*prt)[3] = a, *p = a[0];printf("a[1][2]: %d\n",a[1][2]); //[]的作用 printf("\nA: *prt: %d\n",*prt);printf("A:(*prt+1): %d\n",(*prt+1));printf("A:(*prt+1)[2]: %d\n",(*prt+1)[2]);//printf("*((*prt+1)[2]): %d\n",*((*prt+1)[2])); //直接报错 
} 

        另外,做了一个关于指针退化的实验,*(prt+1)指向的是数组a的第二个数组元素(实验佐证,sizeof指针长度为12),但当再其基础上做加1处理后,其就退化成了指向第二行的首个数据的指针。

		printf("\nAtry: *(prt+1): %d\n",*(prt+1));printf("Atry: sizeof(*(prt+1)): %d\n",sizeof(*(prt+1))); //说明*(prt+1)获取的是第二行的数据printf("Atry: *(prt+1)+1: %d\n",*(prt+1)+1);//*(prt+1)退化成了第二行的第一个数据的地址, printf("Atry: ((*(*(prt+1)+1)): %d\n",(*(*(prt+1)+1)));

        关于数组指针退化的问题,当直接对数组指针变量进行操作(eg. *(prt+1))后再解引用,都不会导致指针退化。除此之外,都会退化到指向某个整形元素。具体原因,*(prt+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。

选项B:* ( * (p+5))

指针p直接指向的数组a的首个数组元素的首个整形元素,因为指针p的数据类型是int,

*(p+5)表示从数组a的首个数组元素的首个整形元素向后数的第5个整形元素的指针所指向的值,

*(*(p+5))表示从数组a的首个数组元素的首个整形元素向后数的第5个整形元素的指针所指向的值作为指针变量所指向的值(不存在嘛!直接报错)。

	//printf("*(*(p+5)): %d\n",*(*(p+5))); //直接报错 printf("\nB: (*(p+5)): %d\n",(*(p+5)));  printf("B: (p+5): %d\n",(p+5));

 

 选项C:( * prt+1)+2

*prt表示数组a的首个元素对应的地址

(*prt+1)表示数组a的第二个元素对应的地址

( * prt+1)+2表示数组a的第4个元素对应的地址

只有再在其基础上,再加一层解引用,才可以表示数组a的第4个元素对应的值

	printf("\nC: *prt: %d\n",*prt);printf("C: (*prt+1): %d\n",(*prt+1));printf("C: (*prt+1)+2: %d\n",(*prt+1)+2);printf("C: *((*prt+1)+2): %d\n",*((*prt+1)+2)); //只有再在其基础上,再加一层解引用,才可以表示数组a的第4个元素对应的值

 

选项D: * ( * (a+1)+2)

a等同于prt,

*(a+1)表示数组a的第二个数组元素的地址,

*(a+1)+2,发生指针退化,*(a+1)此时表示数组a的第二个数组元素中的首个整形元素的地址,整个表示数组a第二行的第二个元素的地址

* ( * (a+1)+2)表示数组a第二行的第二个元素的值

		printf("\nD: *(a+1): %d\n",*(a+1));printf("D: (*(a+1)+2): %d\n",(*(a+1)+2));printf("D: *(*(a+1)+2): %d\n",*(*(a+1)+2));printf("\nD: *(a): %d\n",*(a));printf("D: *(a+1): %d\n",*(a+1));printf("D: *(*a+1): %d\n",*(*a+1));

 

正确答案

选D,* ( * (a+1)+2)

整体代码

int main()
{int a[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};int (*prt)[3] = a, *p = a[0];printf("a[1][2]: %d\n",a[1][2]); //[]的作用 //printf("*((*prt+1)[2]): %d\n",*((*prt+1)[2]));printf("\nAtry: *(prt+1): %d\n",*(prt+1));printf("Atry: sizeof(*(prt+1)): %d\n",sizeof(*(prt+1))); //说明*(prt+1)获取的是第二行的数据printf("Atry: *(prt+1)+1: %d\n",*(prt+1)+1);//*(prt+1)退化成了第二行的第一个数据的地址, printf("Atry: ((*(*(prt+1)+1)): %d\n",(*(*(prt+1)+1)));printf("\nA: *prt: %d\n",*prt);printf("A:(*prt+1): %d\n",(*prt+1));printf("A:(*prt+1)[2]: %d\n",(*prt+1)[2]);//printf("*((*prt+1)[2]): %d\n",*((*prt+1)[2])); //直接报错 //printf("*(*(p+5)): %d\n",*(*(p+5))); //直接报错 printf("\nB: (*(p+5)): %d\n",(*(p+5)));  printf("B: (p+5): %d\n",(p+5));printf("\nC: *prt: %d\n",*prt);printf("C: (*prt+1): %d\n",(*prt+1));printf("C: (*prt+1)+2: %d\n",(*prt+1)+2);printf("C: *((*prt+1)+2): %d\n",*((*prt+1)+2)); //只有再在其基础上,再加一层解引用,才可以表示数组a的第4个元素对应的值printf("\nD: *(a+1): %d\n",*(a+1));printf("D: (*(a+1)+2): %d\n",(*(a+1)+2));printf("D: *(*(a+1)+2): %d\n",*(*(a+1)+2));printf("\nD: *(a): %d\n",*(a));printf("D: *(a+1): %d\n",*(a+1));printf("D: *(*a+1): %d\n",*(*a+1));
} 

参考链接

数组的定义,初始化和使用,C语言数组详解数组可以说是目前为止讲到的第一个真正意义上存储数据的结构。虽然前面学习的变量也能存储数据,但变量所能存储的数据很有限。不仅如此,数组和指针(后续会讲)是相辅相成的http://c.biancheng.net/view/184.html

C语言二维数组指针(指向二维数组的指针)详解二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有缝隙。以下面的二维数组 a 为例: int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; 从http://c.biancheng.net/view/2022.html


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

相关文章

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

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

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…