个人学习时候的一种理解如下:
首先,不管是一维数组还是二维数组,在实际内存中储存的时候都是连续的,只是我们在对其进行了一些操作,来辅助我们来更好的表达数据。
数组A
一维储存0 到 9的数据:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
二维从内存上来看也应该是这样存储的:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
那么问题来了,既然存储方式一样,那二维和一维用指针来表达的话,会有什么不同呢?
容我来分析:
首先,个人认为二维区别于一维的不同之处就在于,二维可以直接获取从首地址开始,每隔N个数据后的地址,也就是说可以直接知道每行地址的首地址,假设N = 3;那就会知道A[0],A[3],A[6]的地址。这时候可以在脑海里改变内存的线性结构(虽然实际还是连续的),切分成一个一个的小条,如下:
&A[0] | 1 | 2 | &A[3] | 4 | 5 | &A[6] | 7 | 8 |
然后进行转换成如下:
&A[0] 0 | 1 | 2 |
&A[3] 3 | 4 | 5 |
&A[6] 6 | 7 | 8 |
然后通过每行的首地址,就可以确定后续元素的地址,然后取值。
既然都已经通过地址去确定数据了,那就把这段内存看称这样吧:
&A[0] | &A[0 + 1] | &A[0+2] |
&A[3] | &A[3+1] | &A[3+2] |
&A[6] | &A[6+1] | &A[6+2] |
然后呢,这就是二维数组经过转换之后的结构了,假设pp指向二维数组的指针,那它应该是什么类型?
通过上边转换的后的图,可以知道pp指向的应该是&A[0];那肯定就是 **PP了;也就是指向指针的指针。
可以再转换一次,变成如下
&A[0] | &A[3] | &A[6] |
&A[0 + 1] | &A[3+1] | &A[6+1] |
&A[0 + 2] | &A[3+2] | &A[6+1] |
既然知道了&A[0],&A[3],&A[6],又知道N,N也就是二维数组的列数,那么图还可简化成
&A[0] | &A[3] | &A[6] |
所以在知道N也就是列数的情况下,二维数组的形式也可以用一维数组的形式来表达。
所以我个人对用二维数组来表达一段内存的理解,可以理解成从起始地址开始,每隔N(列数)个内存地址,压缩成一个空间,并记录这个空间的起始地址,访问时,可以通过这个起始地址,和N进行对数据的访问。
有意思,有点像高数里的高阶求导,求指针就是对函数求导,那么三维数组,里是啥呢?用啥表达?用到的时候在想吧,还有其他事要做告辞
本人新人,只是在学习的时候,想到的这样的理解方式,仅作记录。