1. 程式人生 > >C語言中陣列使用負數值的標記

C語言中陣列使用負數值的標記

·引 對陣列的認知

在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)
顯然這意味著這是記憶體空間中連續的地址,也就是說二維陣列真正的儲存方式任然是線性的,一維的,同理我們可以得知對於三維,乃至更高維的陣列,它其實也無法跳出維度的限制,其實他們都是一維
所以我們應該這樣認識多維陣列

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