본문 바로가기
C++

[C++] 포인터의 이해

by teamnova 2024. 5. 7.

포인터란 무엇인가요?

포인터는 C++ 프로그래밍의 가장 기본적이면서도 중요한 개념 중 하나입니다. 간단히 말해, 포인터는 메모리의 주소를 저장하는 변수입니다. 이를 좀 더 쉽게 이해하기 위해 우리가 살고 있는 도시를 예로 들어볼까요? 각 집에는 고유한 주소가 있습니다. 만약 당신이 친구의 집을 방문하고 싶다면, 그 집의 주소를 알아야 합니다. 포인터도 비슷합니다. 변수의 '집'이라 할 수 있는 메모리 위치를 알고 있어야 그 변수를 사용할 수 있죠.

포인터 사용의 이점은 무엇인가요?

포인터를 사용하면 메모리를 보다 효율적으로 관리할 수 있습니다. 큰 데이터를 다룰 때, 데이터를 복사하여 사용하는 대신 데이터의 주소만 전달할 수 있어, 메모리 사용량을 줄이고 성능을 향상시킬 수 있습니다. 또한, 포인터를 통해 동적 메모리 할당을 다룰 수 있어 프로그램 실행 중에 메모리 크기를 조정할 수 있습니다.


이제 기본적인 포인터의 사용법을 알아보겠습니다. 아래의 예제는 포인터를 선언하고, 초기화하며, 그 값을 사용하는 방법을 보여줍니다.

#include <iostream>

int main() {
    int x = 10;    // 정수 변수 선언
    int* p = &x;   // x의 주소를 저장하는 포인터 p 선언

    std::cout << "x의 값: " << x << std::endl;        // 변수 x의 값 출력
    std::cout << "x의 주소: " << &x << std::endl;    // 변수 x의 메모리 주소 출력
    std::cout << "p가 가리키는 주소: " << p << std::endl; // 포인터 p가 가리키는 주소 출력
    std::cout << "p를 통해 접근한 x의 값: " << *p << std::endl; // 포인터 p를 역참조하여 x의 값을 출력

    return 0;
}


실행 결과:

x의 값: 10
x의 주소: 0x7ffeedf84b8c
p가 가리키는 주소: 0x7ffeedf84b8c
p를 통해 접근한 x의 값: 10



이 예제에서 `int x = 10;`은 변수 x를 선언하고 10으로 초기화합니다. `int* p = &x;`는 변수 x의 주소를 포인터 p에 저장합니다. `&` 연산자는 변수의 주소를 가져오는 연산자입니다. 이 주소는 p가 '가리키는' 주소가 됩니다. 

`std::cout`를 통해 x의 값과 주소, 그리고 포인터 p를 사용하여 x의 주소와 값을 출력합니다. 포인터 p에 `*` 연산자를 사용하여 `*p` (역참조)는 p가 가리키는 주소에 저장된 값을 가져옵니다.

포인터를 사용하면서 가장 중요한 것은 포인터가 유효한 메모리 주소를 가리키고 있는지 확인하는 것입니다. 유효하지 않은 메모리를 가리키는 포인터를 사용하면 프로그램이 오류를 일으킬 수 있습니다.

 

포인터를 사용한 배열 예제
포인터와 배열의 관계를 이해하는 것은 C++에서 중요한 개념 중 하나입니다. 배열의 이름은 그 자체로 배열의 첫 번째 요소를 가리키는 포인터로 사용될 수 있습니다. 이 예제에서는 포인터를 사용하여 배열의 요소에 접근하고, 각 요소의 값을 변경하는 방법을 보여드리겠습니다.

#include <iostream>

int main() {
    int arr[5] = {1, 2, 3, 4, 5}; // 5개의 요소를 갖는 정수 배열 선언 및 초기화
    int* p = arr;                // 배열의 첫 번째 요소를 가리키는 포인터 선언

    std::cout << "배열의 원래 값:" << std::endl;
    for (int i = 0; i < 5; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;

    // 포인터를 사용하여 배열의 값을 1씩 증가
    for (int i = 0; i < 5; i++) {
        *(p + i) += 1;  // p+i는 배열의 i번째 요소를 가리키며, *을 사용하여 그 값을 수정
    }

    std::cout << "포인터로 수정된 배열의 값:" << std::endl;
    for (int i = 0; i < 5; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}


실행 결과:

배열의 원래 값:
1 2 3 4 5 
포인터로 수정된 배열의 값:
2 3 4 5 6



이 예제에서는 먼저 5개의 정수로 이루어진 배열 arr을 선언하고 초기화했습니다. 그리고 int* p = arr;을 통해 포인터 p가 배열 arr의 첫 번째 요소를 가리키게 합니다. 배열 이름 arr 자체가 배열의 첫 번째 요소의 주소와 같기 때문에 이 방식으로 포인터를 초기화할 수 있습니다.

배열의 값을 출력하는 첫 번째 루프에서는 배열의 각 요소를 직접 참조합니다. 두 번째 루프에서는 포인터 p를 사용해 배열의 각 요소에 접근합니다. p + i는 i번째 요소를 가리키며, *(p + i) += 1;은 해당 요소의 값을 1만큼 증가시킵니다.

이 예제를 통해 포인터를 사용하여 배열의 요소를 직접 조작할 수 있음을 알 수 있습니다.