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* 的陣列來轉型,這裡可能不好理解
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]) {};
如此一來就可以完整的傳入鎮列了


範例

/*****************************************************************************
Name : 
Date : 2018/06/13
By   : CharlotteHonG
Final: 2018/06/13
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>

#define WIDTH 2
#define HEIGHT 3

void fun(int** p){
    for(int j = 0; j < HEIGHT; ++j) {
        for(int i = 0; i < WIDTH; ++i) {
            printf("%d, ", p[j][i]);
        } printf("\n" );
    }
}

int main(int argc, char **argv) {
    int arr[HEIGHT][WIDTH]={};
    int* p[HEIGHT];

    for(int j = 0; j < HEIGHT; ++j) {
        p[j]=arr[j];
        for(int i = 0; i < WIDTH; ++i) {
            arr[j][i] = 1;
        }
    }

    fun(p);
    return 0;
}

沒有留言:

張貼留言