2017年11月13日 星期一

C / C++ 函式傳遞二維陣列

C / C++ 函式傳遞二維陣列

二維的傳遞

一般來說我們嘗試傳著一個一維陣列是這樣傳遞的
void fun(int* p){...}

int arr[10]={};
fun(arr);
這種時候確實可行,編譯器會自動將型態 int(*)[10] 轉成 int* 然後成功的輸入。
要注意的是上面兩種型態是不同的,而且型態名稱就如上面上面那樣,一維的時候會自動轉換可是到了二維的時候就出問題,主要是因為編譯器只能轉一維
類類似於以下的代碼
int arr[][]={{0,1},{2,3}};
這是一個錯誤的代碼沒辦法辦法被執行,正確如下
int arr[][2]={{0,1},{2,3}};
你可以想像成編譯器只幫你處理最左邊的 [] 這裡會幫你補
所以一個二維的傳遞方式可以改成這樣
void fun(int (*p)[2]){...}
這樣就可以正常傳遞了,但是會限制住第二維的寬度另外他也相等於以下的寫法
void fun(int p[][2]){...}
這樣寫可能比較好理解

不定長度的二維傳遞

那如果要傳遞不定長的二維就必須使用 int** 了,不過這樣的用法沒辦法直接從int(*)[n] 轉型,你必須手動轉型
如果想要自動轉型成 int** 反推一下就要使用 int* 的陣列來轉型,這裡可能不好理解,就是星星兩邊各加1了。
int* 的陣列只的是一個陣列裡面放著一堆int*
int 的陣列只的是一個陣列裡面放著一堆int
二陣列的意思,可以想像成有一個一維陣列裡面放著一堆一維陣列
int arr1[2][2]{{1,2},{3,4}};

int* p1[2];
p1[0]=arr1[0];
p1[1]=arr1[1];
現在p1可以自動轉換成 int** 了

如何傳遞陣列的長寬

這是轉成指標之後的缺點,他將會遺失陣列的長度資訊,一般處理辦法就是函式多一個參數傳入,或者是拿陣列的第一個數值來當作長度。
C++的樣板可以解決這個問題,寫法如下
template<size_t N, size_t N2>
void priarr(int (&arr)[N][N2]) {};
如此一來就可以完整的傳入鎮列了

沒有留言:

張貼留言