如何將二維數組作為函數的參數傳遞,這是涉及到多維數組時經常要遇到的問題。長期來,我們往往知其然,但不知其所以然。這裡簡單總結一下。
1.《C程序設計》中講到:可以用二維數組名作為實參或者形參,在被調用函數中對形參數組定義時可以指定所有維數的大小,也可以省略第一維的大小說明,如:
void Func(int array[3][10]); void Func(int array[][10]);
二者都是合法而且等價,但是不能把第二維或者更高維的大小省略。兩個示例程序如下:
#include <iostream> using namespace std; void fun(int a[2][2],int n) { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { cout<<a[i][j]<<endl; } } } void main() { int test[2][2]={{1,2},{3,4}}; fun(test, 2); cin.get(); }
上面程序提供了二維數組中兩個維度的大小,再看下面:
#include <iostream> using namespace std; void fun(int a[][2],int n) { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { cout<<a[i][j]<<endl; } } } void main() { int test[2][2]={{1,2},{3,4}}; fun(test, 2); cin.get(); }
上述兩段程序均可正常運行,輸出結果:
為什麼必須要提供第二維度的大小呢?因為編譯階段,編譯器要為a[i][j]正確尋址。a[i][j]的地址為:a+i*列數(第二維大小)+j。
2.如果在函數參數中傳入二維指針int **,二維指針中包含了a、a[0]/a[1]、數據三層結構。
int**已經提供了a[0]及a[1]的地址,這樣在對a[i][j]尋址的過程中,就不需要第二維大小來確定a+i*列數(第二維大小)了。程序如下:
#include <iostream> using namespace std; void fun(int **a,int n) { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { cout<<a[i][j]<<endl; } } } void main() { int **test = new int*[2]; for(int i=0;i<2;i++) { test[i] = new int[2]; } test[0][0] = 1;test[0][1] = 2;test[1][0] = 3;test[1][1] = 4; fun(test, 2); cin.get(); }
3.如果把二維數組名傳遞給int**,編譯階段將會報錯:不能將參數 1 從“int [2][2]”轉換為“int **。因為二維數組的結構和二維指針是不同的,在底層,二維數組的結構和一維數組是一樣的。在二維數組中,a和a[0]均指向數組首地址,而且二維數組是按行順序存儲的。
所以說二維數組和二維指針是大大不同的,二維數組的結構基本和一維數組是一樣的。這樣,把二維數組傳遞給int**的程序也就不難理解了,如下:
#include <iostream> using namespace std; void fun(int **a,int n) { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { cout<<*((int*)a+i*n+j)<<endl;//二維數組a結構實質就是一維數組 //傳入時強制轉化為int**,底層變成了兩層指針結構是錯誤的,這裡要強制轉化為一層結構 //由於強制轉換的int** 是錯誤的,所以不能把它當做二維指針來用,不能使用a[i][j] } } } void main() { int test[2][2]={{1,2},{3,4}}; fun((int **)test, 2); cin.get(); }
我的理解大致就是這樣了。