C언어 이중 포인터 (Double Pointer)
선수학습(1개)
요약
C언어 이중 포인터의 개념과 역참조 방법을 알아봅니다. 포인터의 포인터가 무엇인지, (*pptr)[i] 표현이 어떻게 동작하는지 정보처리기사 실기 대비 핵심 내용을 정리합니다.
이중 포인터 핵심 정리
| 개념 | 설명 | 예시 |
|---|---|---|
| 이중 포인터 | 포인터의 주소를 저장하는 포인터 | int **pptr; |
단일 역참조 *pptr | 이중 포인터가 가리키는 포인터 | *pptr == ptr |
이중 역참조 **pptr | 최종 값에 접근 | **pptr == *ptr == 값 |
이중 포인터란? 쌩기초
이중 포인터 (Double Pointer)는 포인터의 주소를 저장하는 포인터입니다. 즉, "포인터를 가리키는 포인터"입니다.


단일 포인터 vs 이중 포인터 쌩기초
| 구분 | 단일 포인터 | 이중 포인터 |
|---|---|---|
| 선언 | int *ptr; | int **pptr; |
| 저장하는 것 | 변수의 주소 | 포인터의 주소 |
| 역참조 | *ptr (값) | *pptr (포인터), **pptr (값) |
역참조 단계별 이해 기초
역참조는 주소를 통해 값에 접근하는 것입니다. 이중 포인터에서는 *를 몇 번 사용하느냐에 따라 접근하는 대상이 달라집니다.


| 표현 | 의미 | 결과 |
|---|---|---|
pptr | pptr에 저장된 값 (= ptr의 주소) | 1000 |
*pptr | ptr에 저장된 값 (= num의 주소) | 100 |
**pptr | num의 값 | 10 |
구조체 배열에서 이중 포인터 심화
시험에서는 이중 포인터로 구조체 배열의 요소에 접근하거나 값을 복사하는 문제가 출제된 바 있습니다.

(*pptr)[i] 표현의 의미
(*pptr)[i]는 다음과 같이 해석됩니다.
*pptr: pptr이 가리키는 포인터 =ptr(*pptr)[i]:ptr[i]=a[i](ptr이 배열 a의 시작 주소를 저장하고 있으므로,ptr[i]로 배열 요소에 접근할 수 있습니다)
따라서 (*pptr)[i]는 배열의 i번째 요소에 접근합니다.
이 코드는 a[2]의 값 {5, 6}을 a[1]에 복사합니다. 실행 후 배열 a는 {1, 2}, {5, 6}, {5, 6}이 됩니다.
주소를 넣어 (*pptr)[1]을 따라가 보겠습니다.
pptr의 값은1000→*pptr로 주소1000에 접근하면ptrptr의 값은100(= 배열 a의 시작 주소) →ptr[1]은a[1]- 따라서
(*pptr)[1]=ptr[1]=a[1]={3, 4}
| 표현 | 동일한 표현 | 의미 |
|---|---|---|
*pptr | ptr | 배열 a의 시작 주소 |
(*pptr)[0] | ptr[0], a[0] | 첫 번째 구조체 {1, 2} |
(*pptr)[1] | ptr[1], a[1] | 두 번째 구조체 {3, 4} |
(*pptr)[2] | ptr[2], a[2] | 세 번째 구조체 {5, 6} |
함수 매개변수로 이중 포인터 전달 심화
C언어에서 함수에 값을 전달하면 복사본이 전달됩니다. 이중 포인터를 전달해도 마찬가지로 복사되지만, 복사된 값 안에 원본 포인터의 주소가 담겨 있으므로 그 주소를 따라가면 원본 배열을 수정할 수 있습니다.
*(*arr + i) 표현 이해하기
함수 매개변수 int **arr은 이중 포인터입니다.

*(*arr + i) 표현을 단계별로 해석해보면 다음과 같습니다.
| 표현 | 의미 | 동일한 표현 |
|---|---|---|
arr | 함수에 전달된 이중 포인터 (= pp = &p) | &p |
*arr | arr을 역참조 (= p = 배열의 시작 주소) | p |
*arr + i | 배열의 i번째 요소의 주소 (포인터 연산) | p + i |
*(*arr + i) | 배열의 i번째 요소의 값 | *(p + i), p[i] |
결국 *(*arr + i) = 값;은 원본 배열의 i번째 요소를 수정합니다.
주의: 함수 내에서 arr[i]를 쓸 수 없는 이유
매개변수 이름이 arr이라서 arr[i]로 배열 요소에 접근할 수 있을 것 같지만, arr은 int ** 타입이므로 동작이 다릅니다.
arr[i]는 *(arr + i)와 같습니다. arr이 int **이므로 한 번 역참조한 결과는 int * 타입(포인터)이 됩니다. 우리가 원하는 int 타입(정수값)이 아닙니다.
| 표현 | 타입 | 의미 |
|---|---|---|
arr[i] | int * | arr 위치에서 i번째 포인터 (배열 값이 아님) |
*(*arr + i) | int | 배열의 i번째 값 |