C/C++中多維數組做參數情況的詳細解釋

我大二剛學完C語言,之後用來寫矩陣分析的時候想把二維矩陣直接傳到函數裏,結果出現了問題:形參實參類型不一致,無法通過編譯!隨後我就嘗試各種方法(改變形參或者實參的格式),雖然最後通過了不過當時還是沒理解原理。

後來自己把原因分析出來了,現在把它寫出來,希望對碰到同樣問題的朋友有所幫助。

轉載請註明出處,謝謝!

幾個跟參數有關的知識:C/C++的函數形參可以是普通類型、指針、引用。傳值方式有兩種:值傳遞(包括指針)、引用。  傳參時從左往右,結合時從右往左,這個很重要(函數默認值與此有關)。 

參數是指針時,我們一般通過兩種方式實現讀寫:①移動指針 p++  ② p+i(目標位置)或者 p[i],等同於尋址的方式實現,他們實現時在內存裏的操作: 一維 p+0(p[0]) p+1(p[1]) p+2(p[2]) ······ p+(n-1)  (p[n-1]) 由於作圖不太方便,下面的講解就不附圖了。

1、一維數組(指針)  

做參數 一般指針做參數我就不多說了,專門搜這種問題的人應該都懂。

下面說一下一維數組: 一般傳參情況:字符串、整型數組(舉個特例,實際上字符串是字符型數組)。 字符串,我們一般用下面這種方式: 


bool PrintStr(char* str)//char str[]也一樣
{
	if (NULL == str || "" == str)
	{
		return false;
	}
	for (int i = 0; i < strlen(str);i++)//就不考慮效率了,注意不要用sizeof
	{
		cout << str[i] << "  ";
	}
	while ('\0' != *str)//通過指針
	{
		cout << *str++ << "  ";
	}
	return true;
}



2、二維數組做參數



在一維中我們看到,遍歷數組時必須有終止條件,可以是某種標誌也可以規定移動次數。
當到二維的時候這種情況就更爲複雜。很多人定義函數的時候將函數定義爲雙重指針,傳參的時候直接把二維數組名放進去,例如:


//matrix 一維矩陣,m 矩陣行數,n矩陣列數
bool PrintMatrix(int** matrix,int m,int n)
{
	return true;
}


int main(void)
{
	int arr[3][3] = {1,2,3,4,5,6,7,8,9};
	
	PrintMatrix(arr,3,3);
	return 0;
}

這時候會提示錯誤:無法從int[3][3]轉爲int**,類型不兼容!

當然會不兼容!
函數傳參的時候並不是你想的那樣,他需要知道傳入參數的特徵:二維數組,數組每一維佔多大。因爲在函數裏面讀寫實際是以*(p+i) 或者 p++的形式操作的。
二維數組如果那樣操作會怎麼樣?我從第一行跳到第二行,你會這麼寫  p+1 或者 p++,可是函數怎麼操作?
int**p,p+1每次移動sizeof(int*) ==4個字節,*p+1每次會移動sizeof(int)個字節;int p[3][3],p+1每次移動sizeof(p[0]) ==3*4個字節,*p+1每次會移動sizeof(int)個字節。它們是不能等同看待的,否則很容易出現內存錯誤,甚至系統崩潰。

所以在定義函數的時候如果是一維就可以省略,因爲指針是按照sizeof(指針類型)移動;而在二維的時候則必須告訴函數一維以後的數據佈局,這樣它纔不會讀寫錯誤甚至越界,一維部分也可以省略。

從抽象而且直接的角度,你也可以這麼理解:一維的在內存中線性排列,讀寫的時候也是線性操作,所以通過了。當你需要處理的內容是非線性的時候,不僅僅要告訴函數我的內容是非線性的,還要告訴他非線性的特徵:二維數組,數組每一維特徵(空間大小)

例如:

#define M 3
#define N 3
//matrix 一維矩陣,m 矩陣行數,n矩陣列數;
//M、N必須是常數,而且N必須和傳入的參數一致
bool PrintMatrix(int matrix[M][N], int m, int n)
{
	return true;
}
//matrix 一維矩陣,m 矩陣行數,n矩陣列數
//M甚至可以省略,因爲有類型int
bool PrintMatrix(int matrix[][N], int m, int n)
{
	return true;
}


//matrix 一維矩陣,m 矩陣行數,n矩陣列數
//當然可以這麼寫,它本來就是這個樣子!
bool PrintMatrix(int (*matrix)[N], int m, int n)
{
	return true;
}

按照上面的方式完美通過,Perfect!


3、多維數組做參數



多維數組和二維數組類似,只不過需要多加幾個說明:

例如:int p[M][N][K] ,p[0][0][0+1] 指針移動移動一個類型長度4byte==sizeof(int),p[0][0+1][0] 指針移動一個維 K*sizeof(int),p[0+1][0][0]指針移動二維N*(K*sizeof(int))。

#define M 3
#define N 3
#define K 3
bool PrintMatrix(int(*matrix)[N][K], int m, int n,int k)
{
	return true;
}


4、總結



通過上面分析可以看出多維指針比較複雜,很容易出錯。所以實際用的時候一般用其它方法繞過這個問題:數據整理爲一維,處理完後再轉成原形式;用結構體或類;一維一維的處理等。

PS:今天登陸發現編碼出問題,重新編輯了一下



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章