본문 바로가기

카테고리 없음

한번에 이해하는 이중 포인터 사용법과 예제를 통한 실습으로 배우기

1. 이중 포인터란

이중 포인터(Double Pointer)는 포인터의 주소를 저장하는 포인터를 의미합니다. 일반적인 포인터는 변수의 주소를 저장하고 해당 주소를 통해 변수에 접근할 수 있습니다. 하지만 이중 포인터는 포인터의 주소를 저장하는 변수로, 이중 포인터를 통해 포인터를 간접적으로 참조하고 접근할 수 있습니다.

간단히 말해, 이중 포인터는 포인터를 가리키는 포인터라고 볼 수 있습니다. 이를 통해 데이터 형식이나 메모리 구조 등에 대한 유연성을 가지면서도, 복잡한 자료 구조를 다루거나 포인터 배열을 다룰 수 있습니다.

예를 들어, 정수를 가리키는 포인터 변수는 하나의 정수 주소를 저장하고 다른 주소로 이동할 수 있습니다. 그러나 이중 포인터는 포인터 변수의 주소를 저장하고, 간접 참조 연산자를 통해 두 번의 간접 참조를 수행해야 최종적으로 변수에 접근할 수 있습니다.

이중 포인터는 메모리 주소를 다루는 포인터 변수를 동적으로 생성할 때 주로 사용되며, 포인터를 가리키는 함수의 매개변수로도 자주 활용됩니다. 이를 통해 포인터 값의 변경을 함수 내에서도 유지할 수 있습니다.

2. 이중 포인터 사용법

이중 포인터는 포인터를 가리키는 포인터이기 때문에 포인터의 주소를 저장하고 간접 참조 연산을 통해 해당 주소에 위치한 포인터가 가리키는 값을 가져올 수 있습니다. 이중 포인터를 사용하는 방법에 대해 알아보겠습니다.

2.1 이중 포인터의 선언

이중 포인터를 선언하기 위해서는 두 개의 별표(**)를 사용합니다. 예를 들어, 이중 포인터가 정수를 가리키는 포인터인 경우 다음과 같이 선언할 수 있습니다.

int **ptr;

이렇게 선언된 이중 포인터는 정수형 포인터를 가리키는 포인터입니다.

2.2 이중 포인터의 할당

이중 포인터도 일반 포인터와 마찬가지로 메모리를 할당하고 주소를 저장해야 합니다. 이중 포인터의 메모리 할당은 다음과 같은 과정을 통해 이루어집니다.

  1. 이중 포인터에 대한 메모리 할당. (malloc(sizeof(int*))
  2. 이중 포인터가 가리키는 포인터에 대한 메모리 할당. (malloc(sizeof(int))

다음은 이중 포인터를 사용하여 정수형 변수의 주소를 저장하고 값에 접근하는 간단한 예제입니다.

#include <stdio.h>
#include <stdlib.h>

int main() {
    int num = 10;
    int *ptr = &num; // 포인터 변수 선언 및 초기화
    int **dPtr = &ptr; // 이중 포인터 선언 및 포인터 변수의 주소 저장

    printf("%d\n", **dPtr); // 이중 포인터를 통한 값 출력

    return 0;
}

위 코드는 num이라는 정수를 가리키는 포인터 ptr을 선언하고 초기화한 뒤, 이를 이중 포인터 dPtr에 저장합니다. 이후 **dPtr을 통해 값을 출력하면 num의 값인 10이 출력됩니다.

2.3 이중 포인터를 사용한 함수 매개변수 전달

이중 포인터는 함수의 매개변수로 사용될 때 유용하게 활용될 수 있습니다. 함수의 매개변수로 이중 포인터를 사용하면 매개변수로 받은 포인터의 값을 변경할 수 있습니다. 이를 통해 함수 내에서도 포인터 변수의 값을 변경하고 유지할 수 있습니다.

간단한 예제를 통해 이중 포인터를 사용한 함수 매개변수 전달 방법을 알아보겠습니다.

#include <stdio.h>

void changeValue(int **ptr) {
    **ptr = 20; // **ptr을 통해 값을 변경
}

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

    printf("Before change: %d\n", *ptr);

    changeValue(&ptr); // 이중 포인터를 매개변수로 전달

    printf("After change: %d\n", *ptr);

    return 0;
}

위 코드는 changeValue라는 함수를 정의하고, 이 함수의 매개변수로 이중 포인터를 사용합니다. changeValue 함수 내에서 이중 포인터를 통해 값을 변경하면 주소를 전달받은 ptr도 변경된 값을 가리키게 됩니다. 따라서 main 함수에서 ptr을 출력하면 변경된 값인 20이 출력됩니다.

3. 실습 예제를 통한 이중 포인터 이해

실습 예제를 통해 이중 포인터의 사용법과 동작 방식을 이해해보겠습니다.

3.1 실습 예제: 이중 포인터를 사용한 배열 역순 정렬

다음은 이중 포인터를 사용하여 배열을 역순으로 정렬하는 예제입니다.

#include <stdio.h>
#include <stdlib.h>

void reverseArray(int **arr, int size) {
    int *start = *arr; // 배열의 시작 주소
    int *end = *arr + size - 1; // 배열의 끝 주소

    while (start < end) {
        // 포인터를 이용하여 값 스왑
        int temp = *start;
        *start = *end;
        *end = temp;

        // start와 end 포인터를 이동
        start++;
        end--;
    }
}

int main() {
    int size;

    // 배열의 크기 입력 받기
    printf("Enter the size of the array: ");
    scanf("%d", &size);

    // 동적으로 배열 생성
    int *arr = malloc(sizeof(int) * size);

    // 배열의 값 입력 받기
    printf("Enter the elements of the array: ");
    for (int i = 0; i < size; i++) {
        scanf("%d", &arr[i]);
    }

    // 배열 출력
    printf("Original array: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }

    // 이중 포인터로 배열 주소 전달하여 역순 정렬
    reverseArray(&arr, size);

    // 역순 정렬된 배열 출력
    printf("\nReversed array: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }

    // 메모리 해제
    free(arr);

    return 0;
}

위 예제에서는 사용자로부터 배열의 크기와 요소를 입력받아 동적으로 배열을 생성한 뒤, 이를 이중 포인터를 통해 함수로 전달하여 역순으로 정렬합니다. 다음은 예제의 동작 과정을 설명합니다.

  1. 사용자로부터 배열의 크기를 입력받는다.
  2. 입력받은 크기로 동적으로 배열을 생성한다.
  3. 사용자로부터 배열의 요소를 입력받는다.
  4. 생성 및 초기화된 배열을 출력한다.
  5. 배열의 시작 주소와 끝 주소를 이중 포인터로 전달하고, 역순으로 정렬하는 reverseArray 함수를 호출한다.
  6. reverseArray 함수에서는 이중 포인터로 받은 배열의 주소를 통해 실제 배열을 역순으로 정렬한다.
  7. 역순 정렬된 배열을 출력한다.
  8. 동적으로 할당한 배열의 메모리를 해제한다.

이 예제에서는 이중 포인터를 사용하여 배열의 주소를 전달하고 함수 내에서 역순 정렬을 수행합니다. 이를 통해 함수 내에서도 배열의 순서를 변경할 수 있으며, 변화된 배열을 함수 외부에서도 확인할 수 있습니다.