2016-05-31 4 views
-1

2 차원 배열의 차원을 받아들이는 C 언어의 함수 (간단히 말해서, nxn 배열을 말함)를 동적으로 배열에 할당 한 다음 반환합니다.C에서 배열을 동적으로 할당하는 함수 - 둘 사이에 차이가 있습니까?

여기에 메모리를 할당하는 것은 다른 곳에서 해방해야 할 필요가 있기 때문에 시작하는 것이 좋지 않은 것으로 간주 될 수 있지만 큰 문제는 아니라고 생각합니다.

변화 1 - 로컬/반품 배열을 할당, ** 변수 함수 INT를 정의 : 말했다 기능의 두 가지 변화와 관련된 장점/단점이 있는지 궁금하네요

int **create_array(int n) { 
    // define array pointer, allocate array... 
    int **a_ = (int**)calloc(n,sizeof(int*)); 
    for (int i = 0; i < n; i++) 
     a_[i] = (int*)calloc(n,sizeof(int)); 
    return a_; 
} 

int main() { 
    int n = 3; 
    int **array2d = create_array(n) 
    printf("First element: %d%c",array2d[0][0],'\n'); 
    // do stuff... etc... 
} 

변화 2 -/반환 배열 할당에서 아웃 INT ** 매개 변수에 추가 기능 : 분명히

int **create_array_2(int **a_, int n) { 
    // allocate array... 
    a_ = (int**)calloc(n,sizeof(int*)); 
    for (int i = 0; i < n; i++) 
     a_[i] = (int*)calloc(n,sizeof(int)); 
    return a_; 
} 

int main() { 
    int n = 3; 
    int **array2d; 
    array2d = create_array_2(array2d,n); 
    printf("First element: %d%c",array2d[0][0],'\n'); 
    // do other stuff... etc... 
} 

들이 같은 결과를 반환과 같은 작업을 달성하지만,보다/더 효율적/나은 연습 안전한 것으로 간주 하나입니다 다른? 내 의견으로는 2 차 변형은 일을 조금 복잡하게 보이게하지만 2 개 사이의 실제 차이점과 호출 될 때 스택/힙에서 발생하는 것이 궁금하다. 다행히도 이것은 바보 같은 질문이 아닙니다. 그것은 내가 궁금해했던 것입니다. 누군가 공유 할 통찰력이 있다면, 나는 그것을 감사 할 것입니다.

+2

변화 (2)가 이해되지 않는다 단 하나의 시간이 걸린다는 것이다. 함수에 전달 된 매개 변수의 값을 사용하고 있지 않다면 바로 새 값을 할당하는 것입니다. C에서 "in-out parameters"는 없습니다.참조로 패스를 에뮬레이트하기 위해 포인터를 전달할 수는 있지만, 버전 2에서는 그렇지 않습니다. 어쨌든 필요하지 않습니다. 버전 1 만 사용하십시오. –

+3

표시된 코드에는 2D 배열이없고 하나만 가리킬 수있는 요소는 없습니다. 포인터가 배열이 아닙니다! – Olaf

+0

'int ** a'는 포인터 찾아보기 테이블이 아닌 2D입니다. – Michi

답변

-2

IMO는 두 가지 중에서 값을 반환하는 것이 가장 좋습니다. 이 방법은 당신과 발신자 사이에 순수하고 단단한 벽이 있습니다.

"몇 가지 물건을주세요!"

"알았어, 여기 몇 가지가있다."

반면에 실제로 고정 크기의 배열을 할당하려면 왜 포인터가 필요합니까? 리턴 타입을 크기 배열로 캐스트 할 수있는 이유는 무엇입니까?

int (*p2a)[15] = (int(*)[15])create_array_2(15, 15); 

그러면 calloc(15*15,sizeof(int))이됩니다.

+1

이것은 매우 잘못되었습니다! 스택에 큰 배열을 할당하거나 불필요하게 잠재적으로 위험한 캐스트를 할당하는 것과 관련된 실용적인 문제조차도 의미하지 않습니다. 또는 배열에 포인터를 할당하는 것. – Olaf

+0

예치. "왜 포인터로 귀찮아?"라고 썼을 때. 아래의 예제가 포인터를 사용하지 않는다는 것을 암시하려고합니까? 나는'calloc'이 대신 * burgers *를 반환한다고 생각하니? 'p2a'가 "배열에 대한 포인터"를위한 폐렴이라는 뜻 이었습니까? 왜냐하면 그렇지 않기 때문입니다. 당신이 선언 한 것은 * 포인터 배열입니다. * 가르치기 전에 C를 배우십시오. 아마도 당신은 int (* p2a) [15]'를 의미했을 것입니다. ... – Sebivor

+0

@Seb 당신이 말하고자하는 것은 "이봐, 너는 한 켤레를 잊었다." 고마워. 결정된. 왜 포인터를 귀찮게하는지에 관해서는 컴파일러가 간접적 인 포인터를 추가하는 것보다 간단한 수학을 사용하는 것이 좋습니다. :-) –

0

이런 종류의 접근법 내가 무엇을 할 거 야 그래서 아마 여러 번에 mallocfree를 호출하지 않도록 노력 할게요 :

예 1 :

#include <stdio.h> 
#include <stdlib.h> 

int *foo(size_t row, size_t col); 

int main(void){ 
    int *arr; 
    unsigned int row, col, k; 

    printf("Give the ROW: "); 
    if (scanf("%u",&row) != 1){ 
     printf("Error, scanf ROW\n"); 
     exit(1); 
    } 

    printf("Give the COL: "); 
    if (scanf("%u",&col) != 1){ 
     printf("Error, scanf COL\n"); 
     exit(2); 
    } 

    arr = foo(row, col); 
    for (k = 0 ; k < (row * col) ; k++){ 
     printf("%d ",arr[k]); 
    } 

    free(arr); 
} 

int *foo(size_t row, size_t col){ 
    unsigned int i, j; 
    int *arr = malloc(sizeof *arr * row * col); 
    int l = 0; 

    if(arr == NULL){ 
     printf("Error, malloc\n"); 
     exit(3); 
    } 

    for (i = 0; i < row ; i++){ 
     for (j = 0 ; j < col ; j++){ 
      arr[i * col + j] = l; 
      l++; 
     } 
    } 

    return arr; 
} 

출력 :

Give the ROW: 6 
Give the COL: 3 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 

예제 2 (표준 C로 작업하는 경우) :

#include <stdio.h> 
#include <stdlib.h> 

int (*foo(size_t row, size_t col))[]; 

int main(void){ 
    size_t row, col; 


    printf("Give the ROW: "); 
    if (scanf("%zu",&row) != 1){ 
     printf("Error, scanf ROW\n"); 
     exit(1); 
    } 

    printf("Give the COL: "); 
    if (scanf("%zu",&col) != 1){ 
     printf("Error, scanf COL\n"); 
     exit(2); 
    } 

    int (*arr)[col] = foo(row, col); 

    for (size_t i = 0; i < row; i++){ 
     for(size_t j = 0; j < col; j++){ 
      printf("%d ",*(*(arr+i)+j)); 
     } 
    } 

    free(arr); 
} 

int (*foo(size_t row, size_t col))[]{ 
    int (*arr)[col] = malloc(row * col * sizeof(int)); 
    int l=0; 

    if (arr == NULL){ 
     printf("Error, malloc\n"); 
     exit(3); 
    } 

    for (size_t i = 0; i < row; i++){ 
     for(size_t j = 0; j < col; j++){ 
      *(*(arr+i)+j) = l; 
      l++; 
     } 
    } 

    return arr; 
} 

출력 : 여기

Give the ROW: 6 
Give the COL: 3 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 

요점은 두 예제에서 mallocfree의 호출이 장소

+0

을 표시해야합니다. C 표준 중 어떤 부분이 구현을 위해 "커널"을 필요로합니까? 아니면 malloc이 커널을 "방해"해야합니까? – Sebivor

+0

@Seb 바로 당신이 다른 곳에서 생각하고있었습니다. – Michi