관리 메뉴

꿈꾸는 개발자

C언어 이중포인터 매개변수 설명하기!(코딩도장 코드 참고) 본문

프로그래밍언어/C언어

C언어 이중포인터 매개변수 설명하기!(코딩도장 코드 참고)

rickysin 2022. 2. 19. 00:29
  • 이중포인터 매개변수 사용하기! 
#include <stdio.h>
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

void allocMemory(void *ptr, int size)    // 반환값 없음, void 포인터 매개변수 지정
{
    ptr = malloc(size);    // ptr은 allocMemory를 벗어나면 사용할 수 없음
}

int main()
{
    long long *numPtr = NULL;

    // numPtr과 할당할 크기를 넣어줌 
    allocMemory(numPtr, sizeof(long long));

    *numPtr = 10;    // 메모리가 할당되지 않았으므로 실행 에러
    printf("%lld\n", *numPtr);

    free(numPtr);

    return 0;
}

해당 코드를 실행하보면 실질적으로 될 것 같지만, 에러가 발생하게 된다. 에러의 원인은 *numPtr 포인터 변수가 NULL;로 설정돼 있기 때문이다. 

분명 매개변수로 지정해서, 넘겨준 것 같지만 왜 *numPtr에 동적할당된 주솟값이 저장되지 않았는지 의문이 들 수 있다. 

하지만, 실제로, 매개변수는 말 그대로, 함수 내에서 자체적으로 생성되는 변수로 가정해야 한다! 따라서, 이 경우 

allocMemory라는 함수가 실행되면서, 새로운 변수인 void *ptr이 스택 메모리에 생성됨을 의미한다. 즉, 현재 void *ptr의 경우 numptr이 담고 있는 NULL을 담고 있다고 보면 된다

해당 그림을 확인해보면, 처음 ptr의 값은 0 즉 numPtr의 NULL값만 그대로 매개변수로 그대로 받아 온 것이다! 동적할당한 후 그 주솟값만 교체했을 뿐 실질적으로 함수 밖에 있는 포인터 변수 numptr에는 아무런 변화가 일어나지 않는 것이다! 따라서, 함수가 종료되면, 자동으로 사라지는 ptr은 아무런 도움이 되지 않고 있는 것이다! 

 

  • 해결책: 이중포인터 매개변수로 받기!

함수를 선언하고, 매개변수를 만드면, main의 함수가 넘어가는 것이 아닌, 매개변수를 스택에 생선 후 입력한 값만 받아오는 것을 기억해야 한다! 

 

#include <stdio.h>
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

void allocMemory(void **ptr, int size)    // 반환값 없음, void 이중 포인터 매개변수 지정
{
    *ptr = malloc(size);    // void **ptr을 역참조하여 void *ptr에 메모리 할당
}

int main()
{
    long long *numPtr=NULL;

    // 단일 포인터 long long *numPtr의 메모리 주소는 long long **와 같음, 할당할 크기도 넣음 
    allocMemory((void**)&numPtr, sizeof(long long)); //longlong과 void가 서로 호환되지 않기 때문에
    //사전에 void**식으로 인자를 넘기는 것이다. 

    *numPtr = 10;
    printf("%lld\n", *numPtr);

    free(numPtr);    // 동적 메모리 해제

    return 0;
}

해당 코드를 살펴보면, 포인터의 주솟값을 (void**)&numptr 형식으로 넘겨주고, **ptr(이중포인터 변수)변수 선언을 통해 값을 받는 것을 확인할 수 있다. 즉, void **ptr에는 이전처럼 NULL을 인자로 받은 것이 아닌, 실질적인 *numPtr의 포인터 변수의 주솟값을 인자로 받은 것이다. 따라서, *ptr=malloc(size)는 실질적으로 밖에 있는 *numPtr에 동적할당의 주솟값을 입력하게 되고, 이는 함수가 종료되더라도, 실질적으로 *numPtr에 주솟값을 입력했기에 영향력이 지속되는 것이다! 

위 그림처럼, 각 포인터의 역참조값을 잘 추적하는 것이 중요하다! 

 

 

  • 코드 출처: 코딩도장