2016-10-03 3 views
1

동적 배열의 크기를 변경하고 사용자가 즉시 채울 수있는 함수를 작성하려고했습니다. 나는 "realloc을"의 사용에 그것을해야한다고 알고있다 (그래서 나는했고, 그래서 ... 작동)하지만 내 첫 번째 시도는 다음과 같이 보았다 : 함수 본문에서malloc 및 memcpy를 사용하여 동적으로 배열 크기를 변경하는 C

void ChangeDynamicArraySize(int* dArray, int oldSize, int newSize){ 

    int* tempArray = (int*) malloc(sizeof(int) * oldSize); 
    CopyArray(tempArray, dArray, oldSize); 
    free(dArray); 
    dArray = (int*) malloc(sizeof(int) * newSize); 
    CopyArray(dArray, tempArray, oldSize); 

    for (int i = oldSize; i < newSize; i++){ 
     scanf("%i", &dArray[i]); 
    } 
    PrintArray(dArray, newSize); 
    free(tempArray); 
} 

"PrintArray (dArray, newSize와) ; " 올바른 일. 메인에서 호출 할 때 는하지만()는 같은 결과를 제공합니다 - 17891602 - 17891602 - 17891602 - 17891602

dArray가 해제 된 같은 보이는 ...? 하지만 할당 된 기억이 기능을 종료 한 후에 자동으로 해제되지는 않습니다.

그렇다면 이유가 무엇일까요?

+0

A입니다. CopyArray는 memcpy()의 버전입니다. – WJuz

+3

'dArray'가 값으로 전달되고 사용자는 로컬 복사본 만 변경합니다. – deniss

답변

2

C에서 함수 매개 변수는 로컬로 복사됩니다. dArray 값을 변경하면 (*dArray)가 작동하지만 매개 변수로 전달한 dArray (주소)에서 변경 한 내용은 사본이기 때문에이 함수에만 국한됩니다.

배열의 주소 (함수 프로토 타입에 dArray**&array)를 전달하고 대신 포인터를 변경할 수 있습니다.이 같은

뭔가 :

void ChangeDynamicArraySize(int** dArray, int oldSize, int newSize){ 

    int* tempArray = (int*) malloc(sizeof(int) * oldSize); 
    CopyArray(tempArray, *dArray, oldSize); 
    free(*dArray); 
    *dArray = (int*) malloc(sizeof(int) * newSize); 
    CopyArray(*dArray, tempArray, oldSize); 

    for (int i = oldSize; i < newSize; i++){ 
     scanf("%i", dArray[i]); 
    } 
    PrintArray(*dArray, newSize); 
    free(tempArray); 
} 

는 다른 방법으로, 당신은 또한 당신의 새로운 malloc 에드 배열의 주소를 반환 할 수 있습니다 (함수 대신에 값이 없음이 int*를 반환하고).

또한 우수 사례로 not cast the return of malloc을 사용하고 실패했는지 확인하고 changed ERRNO (POSIX API를 사용하는 경우)을 점검 할 수 있습니다.

+0

A, ok ... 알았어, 고마워. :) – WJuz

+0

나는 이것을 시도했지만 scanf ("% i", dArray [i])는 0xCCcccccc 위치 쓰기 액세스 위반을 발생시킨다. – WJuz

+0

하지만 그 중 하나 : scanf ("% i", & (* dArray) [i])는 괜찮은 것 같습니다;) 이제 작동 중입니다. – WJuz

1

블록 범위가있는 dArray에 malloc에 ​​의해 할당 된 새 메모리를 할당하려고합니다. 이 포인터를 호출 함수에 다시 전달해야합니다. dArray은 전달한 포인터의 복사본이며 호출하는 함수로 돌아 가면 원래 포인터는 변경되지 않습니다. dArray 이후

ptr = ChangeDynamicArraySize(ptr, oldSize, newSize); 

함수 호출에 전달 된 포인터의 복사본입니다 당신이 값을 변경하기 때문에 함수의 외부에 표시가되어 있는지, *dArray의 값을 변경하면 :처럼 당신은 함수 호출을해야한다 원래 포인터와 사본 모두가 가리키는 메모리 위치에 저장됩니다. 그러나 함수 안에 dArray 포인터를 재할 당하면이 포인터가 이제 다른 위치를 가리켜 야한다는 것을 알 수 있습니다. 원본은 여전히 ​​원래 위치를 가리 킵니다.

원래 문제의 해결책은 근본적인 문제 앓고 : 당신은 함수의 메모리 섹션에 대한 포인터를 전달하고, 포인터가 메모리 malloc() 또는 calloc() 또는 realloc()를 사용하는 것을 재 할당하는 경우, 새 메모리가 새 주소를 가지고 . realloc()도 마찬가지입니다. 요청 된 메모리를 할당하기에 이전 위치에 연속 바이트가 충분하지 않을 수 있기 때문입니다. 원래 솔루션은 ChangeDynamicArraySize() 함수 안에 메모리를 재 할당 한 다음이 메모리의 내용을 수정합니다. 그러나 반환 후, 호출 함수는 새로운 메모리가 어디 있는지 알지 못합니다. 따라서 새로 할당 된 메모리에 대한 포인터를 호출자에게 반환해야합니다.

@Diti는 포인터의 주소를 배열의 첫 번째 요소에 전달하여이를 해결하기위한 대안을 제안했습니다. 이 포인터는 역 참조되고 새로 할당 된 메모리의 주소 값이 주어질 수 있습니다. 이런 식으로, 호출 함수는 배열 함수의 첫 번째 요소의 주소를 제공하는 포인터를 통해 호출 함수가 배열에 액세스 할 때마다 호출 함수가 더 현명하지 않습니다. 산뜻한. 그러나 나는 가능한 한 포인터를 명시 적으로 전달하는 것을 선호한다고 생각합니다. 그것은 나에게 분명합니다.

+0

흠, dArray는 포인터이므로, 블록에서 수행 된 연산이 변수 외부의 포인터에도 영향을 미칠 것이라고 생각합니다. 변수의 값을 변경하는 것과 같습니다 ... – WJuz

+1

Nope. 함수 안에서는 복사본으로 작업하고 있습니다. 함수에서'* dArray'를 변경하면 원래 포인터와 복사본이 가리키는 메모리에 저장된 값을 변경하기 때문에 함수 바깥 쪽에서 볼 수 있습니다. 그러나 함수 안에 포인터를 재 할당하면 다른 포인터의 복사본 인이 포인터가 이제 다른 곳을 가리켜 야한다는 것을 알 수 있습니다. –

+0

이제, ChangeSize 함수 본체에서 realloc()을 호출하면 realloc()이 MainPointer와 ChangeSizePointer에서 가리키는 메모리 블록을 참조하기 때문에 main()에서도 효과를 볼 수 있다는 것을 이해합니다. 내가 옳다면 .. 위치가 아니라 크기 만 바꾸면 좋겠다. – WJuz

관련 문제