二維陣列當引數傳入

2021-09-30 12:21:08 字數 1599 閱讀 6037

[原文開始] 

可以用二維陣列名作為實參或者形參,在被呼叫函式中對形引數組定義時可以指定所有維數的大小,也可以省略第一維的大**明,如: 

void func(int array[3][10]); 

void func(int array[10]); 

二者都是合法而且等價,但是不能把第二維或者更高維的大小省略,如下面的定義是不合法的: 

void func(int array); 

因為從實參傳遞來的是陣列的起始位址,在記憶體中按陣列排列規則存放(按行存放),而並不區分行和列,如果在形參中不說明列數,則系統無法決定應為多少行多 少列,不能只指定一維而不指定第二維,下面寫法是錯誤的: 

void func(int array[3]);實參陣列維數可以大於形引數組,例如實參陣列定義為: 

void func(int array[3][10]); 

而形引數組定義為: 

int array[5][10]; 

這時形引數組只取實參陣列的一部分,其餘部分不起作用。 

[原文結束] 

大家可以看到,將二維陣列當作引數的時候,必須指明所有維數大小或者省略第一維的,但是不能省略第二維或者更高維的大小,這是由編譯器原理限制的。大家在學編譯原理這麼課程的時候知道編譯器是這樣處理陣列的: 

對於陣列 int p[m][n]; 

如果要取p[i][j]的值(i>=0 && i

p + i*n + j; 

從以上可以看出,如果我們省略了第二維或者更高維的大小,編譯器將不知道如何正確的定址。但是我們在編寫程式的時候卻需要用到各個維數都不固定的二維陣列 作為引數,這就難辦了,編譯器不能識別阿,怎麼辦呢?不要著急,編譯器雖然不能識別,但是我們完全可以不把它當作乙個二維陣列,而是把它當作乙個普通的指 針,再另外加上兩個引數指明各個維數,然後我們為二維陣列手工定址,這樣就達到了將二維陣列作為函式的引數傳遞的目的,根據這個思想,我們可以把維數固定 的引數變為維數隨即的引數,例如: 

void func(int array[3][10]); 

void func(int array[10]); 

變為: 

void func(int **array, int m, int n); 

在轉變後的函式中,array[i][j]這樣的式子是不對的(不信,大家可以試一下),因為編譯器不能正確的為它定址,所以我們需要模仿編譯器的行為把array[i][j]這樣的式子手工轉變為: 

*((int*)array + n*i + j); 

在呼叫這樣的函式的時候,需要注意一下,如下面的例子: 

int a[3][3] = 

, , 

}; func(a, 3, 3); 

根據不同編譯器不同的設定,可能出現warning 或者error,可以進行強制轉換如下呼叫:   

func((int**)a, 3, 3); 

其實多維陣列和二維陣列原理是一樣的,大家可以自己擴充的多維陣列,這裡不再贅述。寫到這裡,我先向看了這篇文章後悔的人道歉,浪費你的時間了。下面是一 個完整的例子程式,這個例子程式的主要功能是求乙個圖中某個頂點到其他頂點的最短路經,圖是以鄰接矩陣的形式存放的(也就是乙個二維陣列),其實這個函式 也是挺有用的,但是我們這篇文章的重點在於將二維陣列作為函式的引數傳遞。

引數傳遞二維陣列

cpp view plain copy void func1 intiarray 10 intmain 編譯通過,注意形參宣告一定要給出第二個維度的大小,要不編譯不過。cpp view plain copy void func2 int parray 10 void func2 1 int parr...

引數傳遞二維陣列

來看 c primer 中給出的方法 void func1 int iarray 10 int main 編譯通過,注意形參宣告一定要給出第二個維度的大小,要不編譯不過。void func2 int parray 10 void func2 1 int parray 編譯通過,無法呼叫 int ma...

引數傳遞二維陣列

來看 c primer 中給出的方法 cpp view plain copy void func1 intiarray 10 intmain 編譯通過,注意形參宣告一定要給出第二個維度的大小,要不編譯不過。cpp view plain copy void func2 int parray 10 vo...