2012-11-15 66 views
1

我都試過,但它不會工作:從函數c返回二維數組正確的方式

#include <stdio.h> 

    int * retArr() 
    { 
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; 
    return a; 
    } 

    int main() 
    { 
    int a[3][3] = retArr(); 
    return 0; 
    } 

我得到這些錯誤:

錯誤3錯誤C2075:「一':數組初始化需要大括號
4智能感知:返回值類型不匹配的功能類型

我在做什麼WRO NG?

+0

請張貼你做了什麼樣的錯誤 – djechlin

+3

需求還沒到那個**的**所有。您返回當您離開作用域時未定義的本地堆棧變量的地址。指針不相容只是傷口中的鹽。 – WhozCraig

+0

出於興趣,您爲什麼要從函數返回二維數組?可能有一個很好的理由想要做到這一點,但這可能不是最好的選擇...... –

回答

6

一個結構是一種方法:

struct t_thing { int a[3][3]; }; 

然後只是返回值的結構。

完整的示例:

struct t_thing { 
    int a[3][3]; 
}; 

struct t_thing retArr() { 
    struct t_thing thing = { 
     { 
      {1, 2, 3}, 
      {4, 5, 6}, 
      {7, 8, 9} 
     } 
    }; 

    return thing; 
} 

int main(int argc, const char* argv[]) { 
    struct t_thing thing = retArr(); 
    ... 
    return 0; 
} 

你所面臨的典型問題是int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};在你的例子指的是在函數返回之後回收的存儲器。這意味着呼叫者閱讀(未定義行爲)並不安全。

的其它方法涉及使所述陣列(其中調用者擁有)作爲參數的功能,或(例如,使用malloc)創建一個新的分配。該結構很好,因爲它可以消除許多缺陷,但對於每種情況都不是理想的。當結構的大小不是恆定或非常大時,您可以避免使用結構體的值。

+3

+1:從seg-fault到正確的最快方式。很好的答案。 – WhozCraig

+0

@WhozCraig謝謝! – justin

+0

當數組很大時,你使用什麼?例如,我需要44k x 2的雙數組。 – sAguinaga

-3

需要返回int**而不是int

+0

錯誤的原因至少有兩個:返回類型是'int(*)[3]',而不是'int **',並且當函數返回時數組不再存在,所以指針值是無效的。 –

+0

@JohnBode:int **沒有錯,只是輸入較少。 (但是返回一個指向堆棧變量的指針肯定是錯誤的。) –

+0

好吧,這就是爲什麼我發佈了問他得到什麼樣的錯誤。我發現編譯錯誤;因爲它是有效的而留下我的答案。我也會說在函數簽名中處理指針比數組更好,但我將在明天展開 – djechlin

-1

對於這一點:

int * retArr() { 
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; 
    return a; 
} 

陣列具有局部範圍的,只要你退出功能破壞。這意味着return a;實際上會返回一個懸掛指針。

若要解決此問題,請將陣列置於全局範圍內,或使用malloc()並將陣列複製到分配的空間中。

1
#include <stdio.h> 

int** retArr() 
{ 
    static int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; 
    return a; 
} 

int main() 
{ 
    int** a = retArr(); 
    return 0; 
} 

您也可以指定返回的變量爲靜態。您還必須在int中聲明變量a,並且不指定尺寸。

+0

該函數返回一個指向包含9個「int」的內存區域的指針。假裝它包含一個指向'int'的指針是非常不正確的,它只會給你帶來麻煩。 –

1

幾個問題:

首先,你不能從初始化函數調用數組;語言定義根本不允許。的char陣列可以用字符串文字進行初始化,如

char foo[] = "This is a test"; 

wchar_tchar16_t,或char32_t可與寬字符串文字初始化,但除此之外,初始化必須是大括號內的列表中的一個陣列值。

其次,你有一個類型不匹配;除非是運算符sizeof或一元運算符&的操作數,或者是在聲明中用於初始化另一個數組的字符串文字,則類型爲「T的N元素數組」的表達式將被轉換爲類型爲「指向T「,表達式的值將是第一個元素的地址;

在函數retArr中,表達式中的a的類型是「3元素數組的3元素數組」int;根據上面的規則,這個將被轉換爲類型的表達式「指針的int 3-元件陣列」,或int (*)[3]

int (*retArr())[3] 
{ 
    int a[3][3] = ...; 
    return a; 
} 

但作爲布倫丹所指出的,一旦離開retArra不再存在;返回的指針值無效。

1

我們可以通過使用堆內存/存儲分配使用STDLIB解決這個問題:

使用STDLIB分配內存可通過malloc和釋放calloc來完成。

創建陣列

  • int ** arr=(int * *) malloc (sizeof (int *) * 5); 
    
    是用於分配5行。
  • arr[i]=(int *)malloc(sizeof(int)*5); 
    
    用於在每個「i」行中分配5列。
  • 因此我們創建了arr [5] [5]。

返回數組:

  • return arr; 
    

我們只需要發送一個指針,它負責訪問該數組像上面。

#include<stdio.h> 
#include<stdlib.h> 
int **return_arr() 
{ 
    int **arr=(int **)malloc(sizeof(int *)*5); 
    int i,j; 
    for(i=0;i<5;i++)//checking purpose 
    { 
     arr[i]=(int *)malloc(sizeof(int)*5); 
     for(j=0;j<5;j++) 
     { 
      arr[i][j]=i*10+j; 
     } 
    } 
    return arr; 
} 
int main() 
{ 
    int **now; 
    now=return_arr(); 
    int i,j; 
    for(i=0;i<5;i++) 
    { 
     for(j=0;j<5;j++) 
     { 
      printf("%d ",now[i][j]); 
     } 
     printf("\n"); 
    } 
    return 0; 
} 
+1

不要在C中輸入'malloc'的結果。 – crashmstr