多維數(shù)組和已經(jīng)討論的普遍的一維數(shù)組相比,差異并不是很大。事實(shí)上,在內(nèi)存中,它們的描述方法和普遍的一維數(shù)組是一樣的。
二維數(shù)組
不要感到意外,最簡單的多維數(shù)組就是二維數(shù)組。一個(gè)二維數(shù)組通常以網(wǎng)格的形式來表示元素。每個(gè)元素通過兩個(gè)下標(biāo)來確定。按照慣例,第一個(gè)下標(biāo)用來確定元素的行值,而第二下標(biāo)用來確定元素的列值。
考慮一個(gè)三行二列的數(shù)組,像這樣定義:
int a [3][2];
C編譯器將為這個(gè)數(shù)組保留6(= 2 X 3)個(gè)整形數(shù)的空間,而且像下面一樣來映射元素:
這張表試圖展示的是a[0][0]引用的元素儲(chǔ)存在6個(gè)元素的一維數(shù)組的開始。元素a[0][1]儲(chǔ)存在下一個(gè)位置(下標(biāo)1),以此類推。在內(nèi)存中,二維數(shù)組的各個(gè)行都是連續(xù)儲(chǔ)存的。一行的最后一個(gè)元素后面緊跟著下一行的第一個(gè)元素。這就是所謂的數(shù)組依行表示法,這也是C/C++編譯器表示數(shù)組的表示方法。
在依行表示法中,編譯器如何確定a[i][j]出現(xiàn)在哪?一個(gè)簡單的公式將通過i和j來計(jì)算下標(biāo)。在這個(gè)例子中,公式為2i + j。并不難看出如何得到這個(gè)公式。每一行有兩個(gè)元素大??;所以行i的第一個(gè)元素的位置為2i。然后該行的j列的位置可以通過j和2i相加得到。這個(gè)分析同樣展示了如何產(chǎn)生N列數(shù)組的公式:N X i + j。注意,這個(gè)公式并不依賴于行的總數(shù)。作為一個(gè)例子,我們來看看gcc如何編譯下面的代碼(使用上面定義的數(shù)組a):
x = a[i ][ j ];
圖5.6展示了這條語句翻譯成的匯編語言。因此編譯器實(shí)質(zhì)上將代碼轉(zhuǎn)換成:
x = *(&a[0][0] + 2*i + j );
而且事實(shí)上,程序員可以以這種方法來書寫,也可以得到同樣的結(jié)果。
選擇依行的數(shù)組表示法并沒有什么魔力。依列的表示法同樣可以工作:
在依列表示法中,各列被連續(xù)儲(chǔ)存。元素[i][j]儲(chǔ)存在i + 3j位置中。其它語言(例如:FORTRAN)使用依列表示法。當(dāng)與多種語言進(jìn)行代碼接口時(shí),這是非常重要的。
大于二維
對(duì)于大于二維的數(shù)組,應(yīng)用了同樣原理的想法。考慮一個(gè)三維數(shù)組:
int b [4][3][2];
在內(nèi)存中,這個(gè)數(shù)組將被當(dāng)作四個(gè)大小為[3][2]的二維數(shù)組被連續(xù)儲(chǔ)存。
下面的表展示了它如何運(yùn)作:
計(jì)算b[i][j][k]的位置的公式是6i + 2j + k。其中6由[3][2]數(shù)組的大小決定。一般來說,對(duì)于維數(shù)為a[L][M][N]的數(shù)組,元素a[i][j][k]的位置將是M £ N £ i + N £ j + k。再次需要注意的是,第一個(gè)維的元素個(gè)數(shù)(L)并沒有出現(xiàn)在公式中。
對(duì)于更高維的數(shù)組,可以通過推廣來做同樣的處理。對(duì)于一個(gè)從D1到Dn的n數(shù)組,下標(biāo)為i1到in的元素的位置可以由下面這個(gè)公式得到:
或者對(duì)于超級(jí)的數(shù)學(xué)技客,它可以用更簡潔地書寫為:
第一維D1,并沒有出現(xiàn)在公式中。
對(duì)于依列表示法,普遍的公式將是:
在這種情況下,是最后一維Dn,不出現(xiàn)在公式中。
在C語言中,傳遞多維數(shù)組參數(shù)
多維數(shù)組的依列表示法在C編程有一個(gè)直接的效果。對(duì)于一維的數(shù)組,當(dāng)任何具體的元素被放置到內(nèi)存中時(shí),數(shù)組的大小并不需要計(jì)算出來。但這對(duì)于多維數(shù)組是不正確的。為了訪問這些數(shù)組的元素,除了第一維的元素個(gè)數(shù),編譯器必須知道其它所有維數(shù)的元素個(gè)數(shù)。當(dāng)一個(gè)函數(shù)的原型帶有一個(gè)多維數(shù)組參數(shù)時(shí),這就變得很明顯了。下面的代碼將不會(huì)被編譯:
void f ( int a[ ][ ] ); /* 沒有維數(shù)信息 */
但是,下面的代碼就會(huì)被編譯:
void f ( int a[ ][2] );
任何有兩列的二維數(shù)組可以傳遞給這個(gè)函數(shù)。第一維的元素個(gè)數(shù)是不需要的。
不要被這類函數(shù)的原型搞混了:
void f ( int * a[ ] );
它定義了一個(gè)一維的整形指針數(shù)組。(它可以附帶用來創(chuàng)建一個(gè)像二維數(shù)組一樣運(yùn)作的數(shù)組。)
對(duì)于更高維的數(shù)組,除了第一維的元素個(gè)數(shù),數(shù)組參數(shù)的其它維數(shù)的必須指定。例如,一個(gè)四維的數(shù)組參數(shù)可以像這樣被傳遞:
void f ( int a[ ][4][3][2] );
更多建議: