原文地址:http://hi.baidu.com/hsyl/blog/item/7731ae519b151c898d5430f9.html

可以用二維數(shù)組名作為實(shí)參或者形參,在被調(diào)用函數(shù)中對(duì)形參數(shù)組定義時(shí)可以指定所有維數(shù)的大小,也可以省略第一維的大小說(shuō)明,如:
void Func(int array[3][10]);
void Func(int array[][10]);
二者都是合法而且等價(jià),但是不能把第二維或者更高維的大小省略,如下面的定義是不合法的:
void Func(int array[][]);
因?yàn)閺膶?shí)參傳遞來(lái)的是數(shù)組的起始地址,在內(nèi)存中按數(shù)組排列規(guī)則存放(按行存放),而并不區(qū)分行和列,如果在形參中不說(shuō)明列數(shù),則系統(tǒng)無(wú)法決定應(yīng)為多少行多少列,不能只指定一維而不指定第二維,下面寫(xiě)法是錯(cuò)誤的:
void Func(int array[3][]);
實(shí)參數(shù)組維數(shù)可以大于形參數(shù)組,例如實(shí)參數(shù)組定義為:
void Func(int array[3][10]);
而形參數(shù)組定義為:
int array[5][10];
這時(shí)形參數(shù)組只取實(shí)參數(shù)組的一部分,其余部分不起作用。

大家可以看到,將二維數(shù)組當(dāng)作參數(shù)的時(shí)候,必須指明所有維數(shù)大小或者省略第一維的,但是不能省略第二維或者更高維的大小,這是由編譯器原理限制的。大家在學(xué)編譯原理這么課程的時(shí)候知道編譯器是這樣處理數(shù)組的,對(duì)于數(shù)組:
int p[m][n],
如果要取p[i][j]的值(i>=0 && i<m && 0<=j && j < n),編譯器是這樣尋址的,它的地址為:
p + i*n + j;
從以上可以看出,如果我們省略了第二維或者更高維的大小,編譯器將不知道如何正確的尋址。但是我們?cè)诰帉?xiě)程序的時(shí)候卻需要用到各個(gè)維數(shù)都不固定的二維數(shù)組作為參數(shù),這就難辦了,編譯器不能識(shí)別阿,怎么辦呢?不要著急,編譯器雖然不能識(shí)別,但是我們完全可以不把它當(dāng)作一個(gè)二維數(shù)組,而是把它當(dāng)作一個(gè)普通的指針,再另外加上兩個(gè)參數(shù)指明各個(gè)維數(shù),然后我們?yōu)槎S數(shù)組手工尋址,這樣就達(dá)到了將二維數(shù)組作為函數(shù)的參數(shù)傳遞的目的,根據(jù)這個(gè)思想,我們可以把維數(shù)固定的參數(shù)變?yōu)榫S數(shù)隨即的參數(shù),例如:
void Func(int array[3][10]);
void Func(int array[][10]);
變?yōu)椋?br>void Func(int **array, int m, int n);
在轉(zhuǎn)變后的函數(shù)中,array[i][j]這樣的式子是不對(duì)的(不信,大家可以試一下),因?yàn)榫幾g器不能正確的為它尋址,所以我們需要模仿編譯器的行為把a(bǔ)rray[i][j]這樣的式子手工轉(zhuǎn)變?yōu)?br>*((int*)array + n*i + j);
在調(diào)用這樣的函數(shù)的時(shí)候,需要注意一下,如下面的例子:
int a[3][3] =
{
      {1, 1, 1},
      {2, 2, 2},
      {3, 3, 3}
};
Func(a, 3, 3);
根據(jù)不同編譯器不同的設(shè)置,可能出現(xiàn)warning 或者error,可以進(jìn)行強(qiáng)制轉(zhuǎn)換如下調(diào)用:
Func((int**)a, 3, 3);

補(bǔ)充:
對(duì)于最后利用指針代替二維數(shù)組的做法稍顯累贅,只需要一層的指針即可:
int a[3][3] =
{
      {1, 1, 1},
      {2, 2, 2},
      {3, 3, 3}
};
函數(shù)使用如下:
Func((int*)a, 3, 3);
函數(shù)聲明如下:
void Func(int *array, int m, int n);
函數(shù)中使用指針如下:
*(array + n*i + j);