2012-11-15 2 views
1

내가 이것을 시도했지만 그것이 작동하지 않습니다올바른 방법이

오류 3 오류 C2075 :

#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; 
    } 

나는 이러한 오류를 얻을 수 '는 ': 함수 타입에게 내가 WRO을하고있는 중이 야 무엇

일치하지 않는 반환 값 유형 : 배열 초기화는 중괄호에게
4 인텔리 필요 응?

+0

어떤 종류의 오류가 발생했는지 게시 해주십시오. – djechlin

+3

** 전혀 ** 할 필요가 없습니다. 범위를 벗어나면 정의되지 않은 로컬 스택 변수의 주소를 반환합니다. 포인터 비 호환성은 상처의 염분에 불과합니다. – WhozCraig

+0

관심의 대상에서 왜 함수에서 2D 배열을 반환하겠습니까? 그것을하기를 원하는 좋은 이유가있을 수 있지만, 아마도 갈 길은 아닙니다 ... –

답변

6

구조체는 하나의 방법입니다.

전체 예 :

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 사용). 구조체는 많은 함정을 없앨 수 있기 때문에 훌륭하지만 모든 시나리오에 이상적이지는 않습니다. 구조체의 크기가 일정하지 않거나 매우 크면 struct를 값으로 사용하지 않아야합니다.

+3

+1 : seg-fault에서 올바른 가장 빠른 방법입니다. 좋은 대답. – WhozCraig

+0

@WhozCraig 감사합니다! – justin

+0

배열이 큰 경우 무엇을 사용합니까? 예를 들어 44k x 2의 double 배열이 필요합니다. – sAguinaga

-3

int**이 아닌 int이 필요합니다. 이를 위해

+0

적어도 두 가지 이유가 잘못되었습니다; 리턴 타입은'int ** '가 아닌'int (*) [3]'이고, 함수가 리턴 할 때 배열은 존재하지 않으므로 포인터 값은 유효하지 않습니다. –

+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()을 사용하고 배열을 할당 된 공간에 복사하십시오.

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

다음 단지 값으로 구조체를 반환 :

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; 
} 

반환 된 변수를 정적으로 지정할 수도 있습니다. 또한 main에서 변수 a를 int **로 선언해야합니다 (차원을 지정하지 않음).

+0

이 함수는 9 개의 int를 포함하는 메모리 영역에 대한 포인터를 반환합니다. 그것이'int'에 대한 포인터를 포함하고있는 것으로 가장한 것은 상당히 부정확하며 두통 이외에 아무것도주지 않을 것입니다. –

1

몇 가지 문제 : 모든

첫째, 당신은 함수 호출에서 배열을 초기화 할 수 없습니다; 언어 정의는 단순히 그것을 허용하지 않습니다. char의 배열은 이러한

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

같은 문자열 리터로 초기화 될 수있다 wchar_t, char16_t가 또는 char32_t 넓은 문자열 리터로 초기화 될 수 있지만, 그렇지 않은 이니셜 브레이스 둘러싸인 목록이어야 배열 값의

두 번째로, 유형 불일치가 있습니다. sizeof 또는 단항 & 연산자의 피연산자이거나 선언의 다른 배열을 초기화하는 데 사용되는 문자열 리터럴 인 경우를 제외하고는 "N- 요소 배열이 T"인 표현식이 " 포인터는 T "이되며, 표현식의 값은 첫 번째 요소의 주소가됩니다.

함수에서 retArr의 표현식에있는 a의 형식은 "3 요소 배열의 3 요소 배열 int"입니다. 위의 규칙에 의해, 이것은 "int의 3 요소 배열 포인터"형식의 표현으로 변환되지 또는 int (*)[3]됩니다

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

을하지만, 브렌든은 지적으로, 한 번 retArr 종료 a는 더 이상 존재; 반환 된 포인터 값이 유효하지 않게됩니다.

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

관련 문제