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

【时时三省】(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.lryc.cn/news/589165.html

相关文章:

  • mac上的app如何自动分类
  • MongoDB 数据库 启用访问控制
  • GitHub 上 Star 数量前 8 的开源 Web 应用项目
  • AI大模型开发架构设计(22)——LangChain的大模型架构案例实战
  • 飞搭系列 | 子事件流节点,让逻辑复用更简单!
  • error: #147: declaration is incompatible with错误解决
  • 从OSI到TCP/IP:Linux网络架构深度解析
  • 【15】MFC入门到精通——MFC弹窗提示 MFC关闭对话框 弹窗提示 MFC按键触发 弹窗提示
  • OpenCV图像自动缩放(Autoscaling)函数autoscaling()
  • 如何加固Web服务器的安全?
  • Volo-HTTP 0.4.0发布:正式支持 HTTP/2,客户端易用性大幅提升!
  • python学习---dayday6
  • AbMole小课堂 | Angiotensin II(血管紧张素Ⅱ)在心血管研究中的多元应用
  • Kimi-K2与DeepSeek-Chat全面对比:哪款AI大模型更强?
  • 【Python】定时器快速实现
  • React响应式组件范式:从类组件到Hooks
  • 嵌入式开发学习(第二阶段 C语言笔记)
  • 文心4.5开源背后的战略棋局:百度为何选择All in开放?
  • Python_1
  • xss-labs 1-8关
  • 零信任安全架构:如何在云环境中重构网络边界?
  • kotlin布局交互
  • 响应式编程入门教程第三节:ReactiveCommand 与 UI 交互
  • IDEA中删除多余的jdk选项 【IDEA2024版】
  • 数仓面试题
  • MongoDB数据问题说明
  • 论文笔记:Learning Cache Replacement with CACHEUS
  • BPE(字节对编码)和WordPiece 是什么
  • [雨云教程]端口冲突该如何解决
  • View2 UI聊天框架源码分享 - 支持[图文视频]混排 加入AI 分享一套功能强大的View2 UI聊天框架源码