[C언어] 이중 포인터(double pointer) 완전 정복

2025. 7. 1. 20:45·개발이야기/C언어
728x90

 

C 언어를 공부하다 보면 int **ptr, char **argv 같은 문장을 마주하게 됩니다. 이때 등장하는 것이 바로 **이중 포인터(double pointer)**입니다.

이중 포인터는 초심자에게 혼란을 주기 쉽지만, 그 개념을 제대로 이해하면 2차원 배열, 포인터 배열, 동적 메모리 할당, 함수 인자 전달 등 다양한 고급 C 문법을 훨씬 쉽게 다룰 수 있습니다.


🧠 이중 포인터란?

이름 그대로, 포인터를 가리키는 포인터입니다. 즉,

  • 일반 포인터 int *p는 정수형 값을 가리키는 포인터이고,
  • 이중 포인터 int **pp는 "정수형 포인터 p를 가리키는 포인터"입니다.

📌 예시 구조

int a = 10;
int *p = &a;    // p는 a를 가리킴
int **pp = &p;  // pp는 p를 가리킴

이 상태에서 각 변수는 다음을 의미합니다:

표현의미

a 정수 값 10
p 변수 a의 주소
*p p가 가리키는 값 → 10
pp 변수 p의 주소
*pp pp가 가리키는 값 → p
**pp *pp가 가리키는 값 → 10

🔍 메모리 구조로 이해하기

변수       값         의미
--------  ----------  --------------------------
a          10         일반 정수 변수
p          &a         a의 주소를 저장 (int *)
pp         &p         p의 주소를 저장 (int **)

실제 메모리 주소가 있다고 가정하면:

주소       변수      값
--------   -------   ------------
0x1000     a         10
0x2000     p         0x1000
0x3000     pp        0x2000

*pp = p = &a, **pp = *p = a


📋 예제: 이중 포인터 선언과 사용

#include <stdio.h>

int main() {
    int num = 10;
    int *ptr = &num;
    int **dptr = &ptr;

    printf("num: %d\n", num);       // 10
    printf("*ptr: %d\n", *ptr);     // 10
    printf("**dptr: %d\n", **dptr); // 10

    **dptr = 20;
    printf("num after change: %d\n", num); // 20

    return 0;
}

이 예제는 **dptr = 20;을 통해 이중 포인터로 원래 변수 값을 수정할 수 있다는 것을 보여줍니다.

✅ 즉, 이중 포인터는 원래 변수의 주소까지 '두 단계'를 거쳐 접근합니다.


🔄 함수에서의 활용: 포인터를 인자로 전달할 때

C에서는 값에 의한 호출(call by value) 방식이기 때문에 함수로 전달된 변수는 복사본입니다. 따라서 함수 내에서 포인터 자체를 바꾸려면 이중 포인터를 사용해야 합니다.

❌ 잘못된 방식 (단일 포인터)

void allocate(int *p) {
    p = malloc(sizeof(int)); // 원래 포인터에는 영향 없음
    *p = 42;
}

✅ 올바른 방식 (이중 포인터)

void allocate(int **p) {
    *p = malloc(sizeof(int));
    **p = 42;
}

int main() {
    int *ptr = NULL;
    allocate(&ptr);
    printf("Allocated: %d\n", *ptr);
    free(ptr);
    return 0;
}

함수에서 메모리를 동적으로 할당하고 그 주소를 반환하려면 반드시 이중 포인터가 필요합니다.


🧭 언제 이중 포인터를 써야 할까?

상황 설명
포인터 자체를 변경해야 할 때 포인터의 주소를 함수로 넘기기 위해 필요 (int **p)
포인터 배열 (문자열 목록 등) char *argv[]는 char **argv 와 동일한 개념
2차원 배열의 동적 할당 int **matrix 형태로 구현 가능
이중 구조를 다룰 때 포인터의 포인터가 필요한 경우 (예: 트리 구조, 링크드 리스트 노드 연결)

📦 이중 포인터로 2차원 배열 만들기

int **matrix;
matrix = malloc(3 * sizeof(int *)); // 행 생성
for (int i = 0; i < 3; i++) {
    matrix[i] = malloc(4 * sizeof(int)); // 각 행에 열 생성
}

matrix[1][2] = 99;
printf("matrix[1][2] = %d\n", matrix[1][2]);

이처럼 이중 포인터를 이용하면 유동적으로 크기를 조절 가능한 2차원 배열을 만들 수 있습니다.

📌 동적 할당을 했으면 free()도 반드시 해줘야 합니다.


✅ 요약 정리

개념 설명
*p 일반 포인터, 값을 가리킴
**pp 이중 포인터, 포인터를 가리킴
&p 포인터 p의 주소 (이중 포인터 생성 시 필요)
함수에 포인터 할당 int **p를 전달하여 malloc 결과 반영 가능
2차원 배열 int ** 구조로 구현 가능
728x90

'개발이야기 > C언어' 카테고리의 다른 글

[C언어] Malloc 파헤치기: 묵시적 할당기  (0) 2025.07.02
[C언어] malloc, free, calloc, realloc 완전 정리 - 힙 영역과 일반 배열의 차이까지  (0) 2025.07.01
[C언어] 문자열과 포인터(char *str) 쉽게 이해하기  (1) 2025.07.01
[C언어] 포인터(pointer) 이해하기: 주소연산자부터 배열까지  (0) 2025.07.01
[C언어 알고리즘] 레드-블랙 트리 삭제, Extra Black 이해부터 Case별 복구까지  (0) 2025.06.22
'개발이야기/C언어' 카테고리의 다른 글
  • [C언어] Malloc 파헤치기: 묵시적 할당기
  • [C언어] malloc, free, calloc, realloc 완전 정리 - 힙 영역과 일반 배열의 차이까지
  • [C언어] 문자열과 포인터(char *str) 쉽게 이해하기
  • [C언어] 포인터(pointer) 이해하기: 주소연산자부터 배열까지
Study & Stack
Study & Stack
하루하루 공부하며 개발 지식을 쌓아가는 공간입니다. 자료구조, 알고리즘, C언어, 시스템 프로그래밍까지 공부한 내용을 ‘Stack’처럼 쌓고 공유합니다.
  • Study & Stack
    Study & Stack
    Study & Stack
  • 전체
    오늘
    어제
    • 목차
      • 크래프톤정글이야기
        • 정글의기록
        • TIL - WIL
      • 개발이야기
        • C언어
        • 파이썬
        • 코딩테스트
        • CSAPP
      • 협업툴
        • git
      • 나의 이야기
        • 내돈내산
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
Study & Stack
[C언어] 이중 포인터(double pointer) 완전 정복
상단으로

티스토리툴바