·引 對數組的認知
在c語言中,我們經常使用的一個結構便是數組,在最開始學習數組的時候,它被描述成這樣(以一維二維數組為例):
一維數組是若干個數連續排列在一起的集合,我們可以通過0-N的標記(N為數組的長度)來訪問每一個元素。
二維數組則是一維數組的集合。
所以在最開始我們對二維數組的概念是這樣的:

然后推而廣之到三維數組

很合理的,我們通過**空間結構**去類比數組的一維與二維,那么問題來了,在計算機當中它又是怎么“類比”這些數組的呢?
我們先看一些代碼
#include <stdio.h>
int main(void)
{
int a[5][5];
for(int i=0,num=0;i<5;i++)
for(int j=0;j<5;j++,num++)
a[i][j]=num;
for(int i=0;i<5;i++){
for(int j=0;j<5;j++)
printf("%5d",a[i][j]);
printf("\n");
}
printf("\na[ 1][ 1]=%2d %p\n",a[1][1],&a[1][1]);
printf("a[ 1][ 2]=%2d %p\n",a[1][2],&a[1][2]);
printf("a[ 1][ 3]=%2d %p\n",a[1][3],&a[1][3]);
}
```
```
運行結果:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
a[ 1][ 1]= 6 000000000062FDE8
a[ 1][ 2]= 7 000000000062FDEC
a[ 1][ 3]= 8 000000000062FDF0
這個結果是顯而易見的,而通過對地址的觀察,我們發現每兩個相鄰的數其間距為4個字節,也驗證了我們認為它是連續的這一認知。而按照約定進行訪問也是我們一般的使用方法。
· 擴展
接下來我們將輸出本部分替換成以下代碼
//這里我們將研究標記如果使用負數將會是什么情況
printf("a[ 0][ 0]=%2d %p\n",a[0][0],&a[0][0]);
printf("a[ 0][-1]=%2d %p\n",a[0][-1],&a[0][-1]);
printf("a[-1][ 0]=%2d %p\n",a[-1][0],&a[-1][0]);
printf("a[-1][-1]=%2d %p\n",a[-1][-1],&a[-1][-1]);
```
一次運行實例
```
a[ 0][ 0]= 0 000000000062FDD0
a[ 0][-1]= 0 000000000062FDCC
a[-1][ 0]= 0 000000000062FDBC
a[-1][-1]= 0 000000000062FDB8
```
或者我們再對a[4][4]進行越界研究,代碼:
```
printf("a[ 4][ 4]=%2d %p\n",a[4][4],&a[4][4]);
printf("a[ 4][ 5]=%2d %p\n",a[4][5],&a[4][5]);
printf("a[ 5][ 4]=%2d %p\n",a[5][4],&a[5][4]);
printf("a[ 5][ 5]=%2d %p\n",a[5][5],&a[5][5]);
```
一次運行實例
```
a[ 4][ 4]=24 000000000062FE30
a[ 4][ 5]= 0 000000000062FE34
a[ 5][ 4]= 5 000000000062FE44
a[ 5][ 5]=25 000000000062FE48
```
實際上這些結果是恰恰符合我們的預期的,因為他們使用的下標超出了數組范圍,所以自然訪問到了數組外內存中的數,這些數是大部分是隨機的。
就像這樣
但是對於以下這些代碼:
```
printf("a[ 1][ 0]=%2d %p\n",a[1][0],&a[1][0]);
printf("a[ 1][-1]=%2d %p\n",a[1][-1],&a[1][-1]);
printf("a[ 1][-2]=%2d %p\n",a[1][-2],&a[1][-2]);
```
其輸出結果為
``` a[ 1][ 0]= 5 000000000062FDE4 a[ 1][-1]= 4 000000000062FDE0 a[ 1][-2]= 3 000000000062FDDC ```
考慮之前的類比,這樣的結果顯然是不合理的,因為如果是二維結構,那么我們所輸出的結果應該為一個內存中的隨機值,但是根據觀察原數組:
```
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
```
我們恰恰可以發現它a[1][-1]與a[1][-2]輸出的恰恰是a[0][4]與a[0][3]的內容。也就是說我們退回了上一行
其實這些問題的答案在觀察數組的地址時就能找到答案:
000000000062FDE0 - 000000000062FDE4= 4 = sizeof(int)
顯然這意味着這是內存空間中連續的地址,也就是說二維數組真正的儲存方式任然是線性的,一維的,同理我們可以得知對於三維,乃至更高維的數組,它其實也無法跳出維度的限制,其實他們都是一維
所以我們應該這樣認識多維數組

(其實這些都是很簡單的東西,但是為此總結一下深化一下印象。因為很多時候第一印象往往是錯的,正如二維數組並不是二維)
