C, C++ 문법

이중 포인터 사용의 의미와 실제 사용례

디버그정 2008. 12. 25. 02:01
일차원적인 포인터 변수는 특정 자료형 값이나 특정되지 않은(void) 값을 지닌 메모리상의 주소 변수이고요.

더블 포인터는 역시 메모리상의 주소 변수이지만
그 값이 포인터(메모리상의 주소)인 변수입니다.
가령 int *a는 a의 값이 인트형 값을 가진 주소 변수이고
int **b는 더블포인터로서 인트형 포인터 값을 가진 주소 변수입니다.

즉 어떤 함수를 만들시 반환되는 값으로 메모리상 주소가 필요할때 사용합니다.
실제로 사용하는 이유는 예를 들자면
HBITMAP CreateDIBSection(
HDC hdc,
CONST BITMAPINFO *pbmi,
UINT iUsage, // color data type indicator: RGB values or palette indices
void **ppvBits, // pointer to variable to receive a pointer to the bitmap's bit values
HANDLE hSection, // optional handle to a file mapping object
DWORD dwOffset // offset to the bitmap bit values within the file mapping object
);

위 api는 비트맵섹션을 생성하는 함수인데...여기서
4번째 인수 void **ppvBits에서 이중 포인터가 사용됨을 볼 수 있습니다.
위 api는 비트맵과 관련된 특정정보(크기라든지, 픽셀수)를 입력하면
그 비트맵 섹션을 생성해주고 위의 void **ppvBits 인수(더블 포인터)에
색상정보의 시작 메모리 주소값을 넣어줍니다...

실제사용은
void *lpColorData;
HBITMAP hBmp=CreateDIBSection(hdc, pbi, DIB_RGB_COLORS, &lpColorData,0,0);
요런식으로 합니다. (이중포인터 부분 주의)
즉 먼저 주소를 나타내는 일차원 포인터를 선언해주고,
위 api에서 인수로 전달하면 lpColorData에 색상 데이터의 주소가 들어갑니다.
일차원 포인터의 주소인 &lpColorData가 이중포인터 형식이 되는 거죠.

void **lppColorData;
HBITMAP hBmp=CreateDIBSection(hdc, pbi, DIB_RGB_COLORS, lppColorData,0,0);
이렇게 사용하면 되지 않느냐고 궁금할겁니다. 그러나 이렇게 사용하면 안됩니다.
왜냐면 lppColorData 이중포인터는 일단 쓰레기 값으로 초기화되는 데
저 api 내부에서는 비트맵 섹션 생성 후 색상 바이너리 데이터가 있는 주소를
*lppColorData에 넘겨주는 식으로 사용하게 될 것입니다.
그런데 쓰레기값은 올바른 주소를 나타낼 수 없기 때문에 메모리 접근 에러가 날 겁니다.

굳이 사용하고자 하면
void *lpColorData;
void **lppColorData = &lpColorData;
HBITMAP hBmp=CreateDIBSection(hdc, pbi, DIB_RGB_COLORS, lppColorData,0,0);
이런식으로 미리 일차원 포인터를 선언해 주고, 이중포인터에 그 주소값을 전달함으로써
올바른 주소를 가리키게 해야 됩니다.
소도 비빌 언덕이 있어야 비빈다는 속담이 생각나네요.
프로그램을 짜다가 보면 함수의 인수로서 포인터 형식의 인수가 있는 경우,,,
그 함수를 사용시에는 항상 그 전 단계의 형식의 선언이 필요함을 알 수 있습니다.
인수가 일차원 포인터의 경우 -> 특정자료형 선언이,,,,
인수가 이차원포인터의 경우 -> 일차원 포인터의 선언이 필요하게 됩니다.


마치 void userfun(int *a)라는 함수를 프로그래머가 만들고
사용시에는 다음과 같이
int a;
userfun(&a);
이런식으로 사용함을 비교해서 곰곰히 생각해보면 알 수 있을겁니다.

실제로 사용하다보면 느끼겠지만 더블이든 트리플이든 모든 포인터는 일차원 포인터의 확장에 불과함을 볼 수 있습니다.
그리고 더블 포인터는 자주 사용하는 개념이니 꼭 숙지하시길 바랍니다.