포인터의 포인터(double pointer)

일반변수의 경우, 변수에 할당된 주소는 포인터를 통해서 접근한다. 그렇다면 포인터 변수의 주소를 저장하거나 접근하려면 어떡해 해야 할까? 이때 포인터의 포인터를 사용한다. 흔히 더블포인터라고도 부르는 포인터의 포인터는 포인터변수 역시 실행시 메모리를 할당받아 메모리 내 임의의 장소에 위치하는데 포인터 변수의 주소를 저장하거나 접근하는데 사용된다.

다음의 프로그램을 실행하면 Segmentation Fault가 발생하면서 프로그램이 종료된다. 그 이유를 찾아보자.
#include <stdio.h>
#include  <stdlib.h>

void AllocMemory(int* ptr);
int main(int argc, char* argv[])
{
      int* ptr = 0;
      AllocMemory(ptr);
      *ptr = 10;
      printf("%d\n", *ptr);
      free(ptr);
}

void AllocMemory(int* ptr)
{
      ptr = (int *)malloc(sizeof(int ));
      *ptr = 10;
      printf("*ptr = %d\n", *ptr);
}
 
실행하면 다음과 같은 실행도중 메모리 오류가 난다.

CERT@proneer:$ ./problem
*ptr = 10
Segmentation fault (core dumped)
CERT@proneer:$

어떠한 문제가 발생한 것일까? 눈치 빠른 사람이라면 이 파트의 제목이 포인터의 포인터이므로 그것과 관계된 것을 쉽게 알 수 있을 것이다.

A라는 함수에서 B 함수를 호출할 때 넘겨준 인자값을 B에서 변경하고 싶다면 어떡해 해야 할까? 일반적으로 호출함수에 포인터의 인자값을 넘겨주면 (Call-by-Reference), 호출함수에서 인자값을 변경한 경우 원래 함수로 돌아간 후에도 그 변경된 값이 유지되는 것을 알 수 있다.

포인터의 경우에도 마찬가지로 포인터의 값을 변경하려면 포인터의 포인터를 넘겨줘야 한다. AllocMemory() 에서 포인터 변수 ptr을 받아서 동적메모리를 할당하고 있다. 여기서 넘겨 받은 ptr은 ptr변수의 자신의 주소가 아니라 ptr이 가리키고 있는 주소이다. 따라서 AllocMemory() 에서 malloc()에 의해 핟아받은 메모리는 ptr변수에 할당되는 것이 아니다.

따라서 포인터를 조작하려면 포인터의 포인터를 넘겨줘야 한다. 위 프로그램은 다음과 같이 변경되야 한다.
#include <stdio.h>
#include  <stdlib.h>

void AllocMemory(int** ptr);
int main(int argc, char* argv[])
{
      int* ptr = 0;
      AllocMemory(&ptr);
      *ptr = 10;
      printf("%d\n", *ptr);
      free(ptr);
}

void AllocMemory(int** pptr)
{
      *pptr = (int *)malloc(sizeof(int ));
      **pptr = 10;
      printf("**pptr = %d\n", **pptr);
}


Reference : C/C++ 개발자는 위한 KIN 포인터 실무

[프로그래밍/_ C/C++] - [C언어] 포인터와 const 키워드
[프로그래밍/_ C/C++] - [C언어] void 형 포인터
[프로그래밍/_ C/C++] - [C언어] 널포인터(NULL)
Posted by Proneer

댓글을 달아 주세요

  1. 감사

    제 블로그에 담아갑니다. 설명이 쉽게 되어있네요~

    2007.07.10 17:17 [ ADDR : EDIT/ DEL : REPLY ]