数组那点事

一点愚见,与大家交流,从语义的角度来理解这个问题,以及为什么要这么设计

 

int A[3]={1,2,3};

物理意义篇

这里的A的物理意义是什么?A是一个数组的名字,代表的是整个数组证据:sizeof(A)=12;

 

自然&A代表A的地址,那么&A+1表示什么意思呢?因为A代表的是整个数组,因而&A+1这个地址就在整个数组A的后面,也就是B的首地址,其值就相当于把A的地址加上整个数组占的字节数(3*4)。实际上&A+1这个地址现在是非法的,那它的作用是什么呢?对了,应该是为二维或更高维的数组服务的。

          

  图(1)B,C定义为A的外部元素,1,2,3定义为A的内部元素

现在问题来了,上面的办法只能找到A,或者A的外部元素,如何访问A的内部元素呢?

这个时候数组的名字A用上了:

第一个办法:第一个元素可以用A[0],第二一个元素A[1] 。。。。。。

但这个办法还不过隐,汇编一般是用基址+偏移地址的方式访问,因而提出了基址+偏移地址的方式,于是有了第另一种访问方式,(实际上第二种方式可能更早)

第二个办法:那把名字A用作基地址,访问第一个元素可用*(A+0)= *A,第二个元素*(A+1) 。。。。。

综上所述:

这是为了解决不同问题引入的两套机制,一个是为了访问内部元素,一个是为了访问外部元素,而刚好A的地址&A和把名字A作为基地址在数值上是相等的。

 

本质篇

虽然&A和A的访问方式是为了解决访问外部元素和内部元素提出的不同方法,但本质上都是一样的。

 

  从图(1)可以看出&A和A的运算用共同基地址,实际上&A和A的差别就在于偏移量,&A运算的偏移量整个数组占的字节数的倍数,而A运算的偏移量是A中一个元素占的字节数的倍数

 

在&A中&这个运算符不仅取得了整个数组的基地址,而且还定义了&A=&A+0是偏移量为0倍数组字节数, &A+1的偏移量为1倍的数组字节数,&A+2的偏移量为整个数组字节数的2倍。

 

同样在可以把A表示成A前面有一个空运算符,这个空运算符不仅获得了A的基地址,而且定义了 [空运算符]A+1的偏移量为一个元素的字节数的1倍。

 

这些运算符不仅要获得基地址,更重要的是他们规定了偏移量。

不同偏移量的运算符都是首先要获得基地址,而基地址是一样。

运用上面这一条我们尝试来理解二维数组:

int A[3][3];

printf("%p\n", A);          //   1

printf("%p\n", &A);         //   2

printf("%p\n", &A [0]);      //   3

printf("%p\n", A [0]);      //   4

printf("%p\n", &A[0][0] );      //   5

printf("%p\n", &A + 1);     //   6

printf("%p\n", A+1);          //   7

(1) A的物理意义代表的是整个二维数组,那么很自然第6语句表示就是指向下一个3*3的二维数组的首地址

(2) 第1条语句表示相当对A做空运算,这条表示对A取地址,偏移量为0倍 元素占的字节数,也就是基地址。这里说一下元素的概念:A是二维数组,所以A的元素就是一维数组,这个可以通过第7条语句验证。同理三维数组的元素是二维数组。

(3) 第2语句条表示相当对A做&运算,这条表示对A取地址,偏移量为0倍 二维数组占的字节数,也就是基地址。

(4) 在这里A[0]是一个一维数组,语句3,4可以用前面一维数组的方式来理解即可。

(5) 第5条语句说的是一个很直观的意思,首地址和第一个元素的地址是一样的。现在要思考的是,C语言的数组下表为什么从0开始,而不是从1开始?其原因就是她采用的是用偏移量来访问数组,那么数组第一个元素的偏移量自然就是0.这一点在《c专家编程》里有提到。

扩展篇

有一个问题不能回避就是数组名与指针的关系,数组名什么时候需要转化成指针?

当数组作为一个参数传递给函数时,假设不将其转化成指针会发生什么情况?

参数是靠栈传递,而栈的大小是受限制的,数组数据量大的情况下这就传不了,所以需要将数组名退化成指针。而退化过程就是通过数组名获得基地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值