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:今天登陸發現編碼出問題,重新編輯了一下




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM