当前位置: 首页 > web >正文

【时时三省】(C语言基础)通过指针引用多维数组

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省

指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。但在概念上和使用方法上,多维数组的指针比一维数组的指针要复杂一些。

1.多维数组元素的地址

为了说清楚指向多维数组元素的指针,先想一下多维数组的性质,以二维数组为例设有一个二维数组a,它有3行4列。它的定义为

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个元素(即4个列元素)。例如,a [ 0 ]所代表的一维数组又包含4个元素:a [ 0 ] [ 0 ],a[0][1],a[0][2],a[0][3],可以认为二维数组是“数组的数组”,即二维数组a是由3个一维数组所组成的。

从二维数组的角度来看,a代表二维数组首元素的地址,现在的首元素不是一个简单的整型元素,而是由4个整型元素所组成的一维数组,因此a代表的是首行(即序号为0的行)的起始地址。a +1代表序号为1的行的起始地址。如果二维数组的首行的起始地址为2000,一个整型数据占4个字节,则a +1的值应该是2000 + 4×4 = 2016(因为第0行有4个整型数据)。a +1指向a[1],或者说,a +1的值是a[1]的起始地址。a + 2代表a[ 2 ]的起始地址,它的值是2032。

a [ 0 ],a [ 1 ],a [ 2 ]既然是一维数组名,已知,数组名代表数组首元素地址,因此a [ 0 ]代表一维数组a [ 0 ]中第0列元素的地址,即& a[0][0]。同理,a[ 1 ]的值是&a [ 1 ] [ 0 ], a [ 2 ]的值是&a[2][0]。

请考虑a数组0行1列元素的地址怎么表示? a [ 0 ]是一维数组名,该一维数组中序号为1的元素的地址显然应该用a [ 0 ] +1来表示。此时“a [ 0 ] +1”中的1代表1个列元素的字节数,即4个字节。a[0]的值是2000,a [ 0 ] +1的值是2004(而不是2016),这是因为现在是在一维数组范围内讨论问题的,正如有一个一维数组x,x+1是其第1个元素x [ 1 ]的地址一样。a [ 0 ] + 0,a [ 0 ] +1,a [ 0 ] + 2,a [ 0 ] + 3分别是a [ 0 ] [ 0 ],a [ 0 ] [ 1 ],a[0][2]a[0][ 3 ]元素的地址(即& a [ 0 ] [ 0 ],& [ 0 ] [ 1 ],&[ 0 ] [ 2 ],& [ 0 ] [ 3 ])。

前已述及,a [ 0 ]和* ( a + 0 )等价,a [ 1 ]和*( a +1 )等价,a [i]和*( a + i )等价。因此,a [ 0 ] +1和* ( a + 0 ) +1都是& a [ 0 ] [ 1 ]。a [ 1 ] + 2和* ( a +1 ) + 2的值都是&a [ 1 ] [ 2 ]。请注意不要将* ( a +1 ) + 2错写成* ( a +1 + 2 ),后者变成* ( a + 3 )了,相当于a [ 3 ]。

进一步分析,欲得到a [ 0 ] [ 1的值,用地址法怎么表示呢?既然a [ 0 ] +1和= ( a + 0 ) +1是[ 0 ] [ 1 ]的地址,那么,* ( a [ 0 ] +1 )就是a [ 0 ] [ 1 ]的值。同理,* ( * ( a + 0 ) +1 )或* ( * a +1 )也是a [ 0 ] [ 1 ]的值。* ( a [ i ] + j )或* ( * ( a + i ) + i )是a [i][j]的值。务请记住* ( a + i )和a [ i ]是等价的。

a [ i ]的性质作进一步说明。a [ i ]从形式上看是a数组中序号为i的元素。如果a是一维数组名,则a [ i ]代表a数组序号为i的元素的存储单元。a [ i ]是一个有确定地址的存储单元。但如果a是二维数组,则a[i]是一维数组名,它只是一个地址,并不代表一个存储单元,也不代表存储单元中的值(如同一维数组名只是一个指针常量一样)。a,a + i,a [ i ],* ( a + i ),* ( a + i ) + j,a[ i ]+ j都是地址。而* ( a [ i ] + j )和* ( * ( a + i ) + j )是二维数组元素a [ i ] [ j ]的值。

a +1和* ( a +1 )的值都是2016。有些人认为a +1是地址,* ( a +1 )是该地址指向的存储单元中的内容,怎么会是同一个值呢?的确,二维数组中有些概念比较复杂难懂,要仔细消化,反复思考。

首先说明,a +1是二维数组a中序号为1的行的起始地址(序号从0起算),而*(a +1)并不是a +1单元的内容(值),因为a +1并不是一个数组元素的地址,也就谈不上存储单元的内容了。* ( a +1 )就是a [ 1 ],而a [ 1 ]是一维数组名,所以也是地址,它指向a [ 1 ] [ 0 ]。a[ 1 ]和* (a +1 )都是二维数组元素a [ 1 ] [ 0 ]的地址的不同的表示形式。

说明:C语言的地址信息中既包含位置信息(如内存编号2000),这包含它所指向的数据的类型信息。现在a [ 0 ]是一维数组名,它是一维数组中起始元素的地址,a是二维数组名,它是二维数组的首行起始地址,二者的纯地址是相同的;即2000,但它们的基类型不同,即它们指向的数据的类型不同,前者是整型数据,后者是一维数组。如果用一个指针变量pt来指向此一维数组,应当这样定义:int ( * pt ) [ 4 ] ;表示pt指向由4个整型元素组成的一维数组,此时指针变量pt的基类型是由4个整型元素组成的一维数组。

再次强调:二维数组名(如a)是指向行(一维数组)的。因此a +1中的“1”代表一行中全部元素所占的字节数。一维数组名(如a [ 0 ],a [ 1 ])是指向列元素的。a [ 0 ] +1中的1代表一个a元素所占的字节数。在指向行的指针前面加一个*,就转换为指向列的指针。例如,a和a +1是指向行的指针,在它们前面加一个*就是* a和* ( a +1 ),它们就成为指向列的指针,分别指向a数组0行0列的元素和1行0列的元素。反之,在指向列的指针前面加&,就成为指向行的指针。例如a [ 0 ]是指向0行0列元素的指针,在它前面加一个8,得& a[0],由于a [ 0 ]与* ( a + 0 )等价,因此& a [ 0 ]与& * a等价,也就是与a等价,它指向二维数组的0行。

注意:不要把& a [ i ]简单地理解为a [i]元素的存储单元的地址,因为并不存在a [ i ]这样一个实际的数据存储单元。它只是一种地址的计算方法,能得到第i行的起始地址,& a [ i ]和a[ i ]的值是一样的,但它们的基类型是不同的。& a[ i ]或a + i指向行,而a [ i ]或* ( a + i )指向列。当列下标j为0时,& a[i]和a[i](即a[i]+j)值相等,即它们的纯地址相同,但应注意它们所指向的对象的类型是不同的,即指针的基类型是不同的。* ( a + i )只是[ i ]的另一种表示形式,不要简单地认为* ( a + i )是“a + i所指单元中的内容”。在一维数组中a + i所指的是一个数组元素的存储单元,在该单元中有具体值,上述说法是正确的。而对二维数组,a + i不是指向具体存储单元而是指向行(即指向一维数组)。在二维数组中,a + i、a [ i ],* ( a + i ),& a [ i ],&a[i][0]的值相等,即它们都代表同一地址,但基类型不同。

 

http://www.xdnf.cn/news/15575.html

相关文章:

  • 视频编码中熵编码之基于上下文的变长编码(Huffman霍夫曼编码和指数哥伦布)
  • 网络编程-epoll模型/udp通信
  • css 边框颜色渐变
  • 【linux V0.11】init/main.c
  • JAVA青企码协会模式系统源码支持微信公众号+微信小程序+H5+APP
  • Spring MVC 执行流程详解:一次请求经历了什么?
  • 基于铸造机床的Canopen转Profinet协议转换网关应用研究
  • 涨停板池,跌停板池,炸板池,次新股池,强势股池数据接口
  • Python命令行计算2的22次方方法
  • 轻松管理多个Go版本:g工具安装与使用
  • keeplived双击热备配置
  • Spring Security 实践及源码学习
  • 如何轻松将音乐从安卓设备传输到安卓设备
  • 504网关超时可能是哪些原因导致?
  • 短剧小程序的「技术革命」:从「粗放生长」到「精准运营」
  • Docker镜像导入、导出操作指南
  • 工业喷涂机器人的革新:艾利特协作机器人引领人机交互新纪元
  • Zookeeper入门安装与使用详解
  • PyTorch 数据加载实战:从 CSV 到图像的全流程解析
  • OpenCV 对数变换函数logTransform()
  • 手提式干粉灭火器检查工作,如何做到可执行、可追溯、可管理?
  • 基于深度学习的LSTM、GRU对大数据交通流量分析与预测的研究
  • 06-C语言:第06天笔记
  • 通过 1Panel MCP 自动部署静态网站
  • Flink Watermark原理与实战
  • Python 中 sys 库的全面解析与实战应用​
  • Agentic AI 的威胁与缓解措施
  • 【编程】-环形缓冲区
  • Basilisk库教程(二)
  • TimSort 类:论Arrays.sort的稳定性