2013-06-05 91 views
3

我在這裏讀了很多東西,並嘗試了很多,但我找不到一種方法將多維數組傳遞給C中的函數,更改了某些值並以某種方式返回了新數組。 重要的是找到一種方法將該數組傳遞給另一個函數並執行相同的操作。操作函數中的多維數組

我想找到一種方法將數組傳遞給函數。然後將它從第一個函數傳遞到第二個函數,在那裏做一些事情(可能是打印,也許更改值),然後再次使用它到第一個函數並最終在main中使用該數組。

我的最後一次嘗試是:

void func(int multarray[][columns]){ 
    multarray[0][0]=9; 
} 

int main(){ 
    int rows; 
    int columns; 
    int multarray[rows][columns]; 
    func(multarray); 
    return 0; 
} 

我也試過這樣:

void func(int multarray[rows][columns]){ 
    multarray[0][0]=9; 
} 

int main(){ 
    int rows; 
    int columns; 
    int multarray[rows][columns]; 
    func(multarray); 
    return 0; 
} 

我也試過這樣:

int 
getid(int row, int x, int y) { 
      return (row*x+y); 
} 

void 
printMatrix(int*arr, int row, int col) { 
    for(int x = 0; x < row ; x++) { 
      printf("\n"); 
      for (int y = 0; y <col ; y++) { 
       printf("%d ",arr[getid(row, x,y)]); 
      } 
    } 
} 

main() 
{ 

    int arr[2][2] = {11,12,21,22}; 
    int row = 2, col = 2; 

    printMatrix((int*)arr, row, col); 

} 

here

我也試過雙PO inters.I還讀到,如果編譯器不支持VLA,則有不同的方法。我正在使用gnu。

+0

你沒有定義ROWS和COLUMNS? – Lucas

+0

@Lucas不,我did.I只是編輯問題 – Dchris

+0

在你的第二個例子中,你永遠不會定義行和列的大小。另外,主要局部變量影響全局定義。 – Lucas

回答

5

不能完全確定,問題是什麼,但這個工作(並打印值「9」):

#include <stdio.h> 

#define ROWS 10 
#define COLUMNS 10 

void func2(int multarray[][COLUMNS]){ 
     multarray[1][4]=10; 
} 

void func1(int multarray[][COLUMNS]){ 
     multarray[0][3]=9; 
     func2(multarray); 
} 

int main(){ 

     int multarray[ROWS][COLUMNS]; 
     func1(multarray); 
     printf("%d\n", multarray[0][3]); 
     printf("%d\n", multarray[1][4]); 
     return 0; 
} 

注意,傳遞給函數時數組衰變爲指針。

+0

如果我想將函數中的數組傳遞給另一個函數,那該怎麼辦呢?它的工作方式是一樣的嗎? – Dchris

+0

數組作爲指針傳遞。所以他們都引用數組的同一個實例。 – Lucas

+0

它被稱爲通過引用傳遞。 –

0

將數組看作指向內存是有幫助的。然後,它很容易聯想到一個二維數組的指針的指針(有點)

這的內存行不通

int arr[2][2] = {11,12,21,22}; //not going to work 

但這個工作對我蠻好

1 #include <stdio.h> 
2 
3 
4 main() 
5 { 
6 int arr[2][2] = {{11,1},{2,21}}; 
7 int row = 2, col = 2; 
8 int i,j; 
9 
10 for(i=0;i<row;i++) 
11  for(j=0;j<col;j++) 
12   printf("%d - ",arr[i][j]); 
13 
14 
15 } 
+1

這不是回答我的問題,改變函數內數組的值並返回這些值。 – Dchris

3

對於你的2維數組,我會爲它定義一個類型。

typedef int my2DArray_t[ROWS][COLUMNS]; 

然後,您可以聲明此類型的變量和指向它們的指針。這使得更容易傳遞信息。

void someFuncOther (my2DArray_t *someArray) 
    { 

    /* Set some values in array */ 
    (*someArray)[1][1] = 4; 

    } 

void someFunc (my2DArray_t *someArray) 
    { 

    /* Set some values in array */ 
    (*someArray)[1][0] = 7; 

    /* Have someFuncOther do some more work */ 
    someFuncOther (someArray); 

    } 


int main (void) 
    { 
    /* This is the actual array */ 
    my2DArray_t myArray; 

    /* Set some values in array */ 
    myArray[0][2] = 6; 

    /* Have someFunc do some work on myArray by passing a pointer to it */ 
    someFunc (&myArray); 

    } 
9

幾件事情要記住:

  1. 當傳遞數組表達作爲參數的函數,它將從型「T N元件陣列的表達被轉換「到」指向T的指針「,表達式的值將是數組第一個元素的地址。被調用的函數接收一個指針值。

  2. []運算符可以與數組或指針類型的表達式一起使用; IOW,如果聲明int a[10]; int *p = a;,則p[i]a[i]指向相同的元素。

  3. 當聲明一個接受VLA作爲參數的函數時,必須在聲明數組的之前聲明指定尺寸爲的參數。

因此,對於操縱一個2D VLA的函數,你會喜歡寫東西

void foo(size_t rows, size_t cols, int (*multiarray)[cols]) // or multiarray[][cols] 
{ 
    size_t i, j; 

    for (i = 0; i < rows; i++) 
    for (j = 0; j < cols; j++) 
     multiarray[i][j] = some_value(); 
} 

怎麼了int (*multiarray)[cols]?請記住,在將數組表達式作爲參數傳遞時,數組表達式的類型將從「N元素數組T」轉換爲「指向T」。在這種情況下,T爲「colsint - 元素陣」,讓我們從「的intcols - 元素阿雷的rows - 元素陣列」到「指針colsint - 元素陣列」去。在函數參數聲明的上下文中,T a[N],T a[]T *a都是相同的;在所有三種情況下,a被宣佈爲指針T。所以int (*multiarray)[cols]相當於int multiarray[][cols],相當於int multiarray[rows][cols]。我更喜歡使用第一種形式,因爲它最準確地代表了情況。

如果你想這個數組作爲參數傳遞給另一個函數,你會使用相同類型:

void bar(size_t rows, size_t cols, int (*multiarray)[cols]) 
{ 
    foo(rows, cols, multiarray); 
} 

int main(void) 
{ 
    size_t rows = 0; 
    size_t cols = 0; 

    // you must assign values to rows and cols before declaring a VLA with them 
    rows = ...; 
    cols = ...; 

    int arr[rows][cols]; 

    bar(rows, cols, arr); 
    ... 
} 

foo所做的數組內容的任何更改將反映在barmain

VLA可能有用,但它們有其侷限性。它們不能被聲明爲static,它們也不能在函數之外定義。他們不能使用{}式初始化語法。此外,VLA支持現在是2011年標準的可選,所以您不能依賴於它們在任何地方的支持。

如果您沒有可用的VLA,並且您的陣列大小在運行時才知道,則必須使用動態內存分配(malloccalloc),並且您傳遞給函數的類型將爲不同:這種方法

void foo(size_t rows, size_t cols, int **multiarray) 
{ 
    size_t i, j; 

    for (i = 0; i < rows; i++) 
    for (j = 0; j < cols; j++) 
     multiarray[i][j] = some_value(); 

} 

void bar(size_t rows, size_t cols, int **multiarray) 
{ 
    foo(rows, cols, multiarray); 
} 

int main(void) 
{ 
    size_t rows; 
    size_t cols; 
    int **multiarray = NULL; 

    ... // get rows and cols 

    // allocate memory for pointers to each row 
    multiarray = malloc(sizeof *multiarray * rows); 
    if (multiarray) 
    { 
    size_t i; 
    // allocate each row 
    for (i = 0; i < rows; i++) 
    { 
     multiarray[i] = malloc(sizeof *multiarray[i] * cols); 
     if (!multiarray[i]) 
     break; 
    } 

    if (i < rows) 
    { 
     // malloc failed for one of the multiarray rows; we need to 
     // free whatever memory has already been allocated and exit 
     while (i--) 
     free(multiarray[i]); 
     free(multiarray); 
     exit(0); 
    } 
    } 

    bar (rows, cols, multiarray); 
    ... 

    if (multiarray) 
    { 
    size_t i; 

    for (i = 0; i < rows; i++) 
     free(multiarray[i]); 
    free(multiarray); 
    } 
} 

一個缺點是,所分配的存儲器不能保證是連續的(即,行不會在存儲器相鄰的)。如果那件事情,你必須去與另一個方法。相反,單獨分配的行和列,你在一個單獨的塊分配的一切,並手動映射數組索引:

void foo(size_t rows, size_t cols, int *fakemultiarray) 
{ 
    size_t i, j; 

    for (i = 0; i < rows; i++) 
    for (j = 0; j < rows; j++) 
     fakemultiarray[ i * rows + j ] = some_value(); 
} 

void bar(size_t rows, size_t cols, int *fakemultiarray) 
{ 
    foo(rows, cols, fakemultiarray); 
} 

int main(void) 
{ 
    size_t rows; 
    size_t cols; 
    int *fakemultiarray = NULL; 

    ... // get rows and cols 

    fakemultiarray = malloc(sizeof *fakemultiarray * rows * cols); 
    if (fakemultiarray) 
    bar(rows, cols, fakemultiarray); 

    ... 
    free(fakemultiarray); 
} 

在這種情況下,我們分配一個緩衝區足夠大的所有元素,但我們必須將其索引爲一維數組,計算索引爲i * rows + j