IMCAT.DEV
로그인 가입
C++ 입문 자료구조

C++ 포인터 (Pointers)

C++ 포인터 (Pointers) — 초급

포인터 (Pointers)

1. 도입 (왜 배워야 하는가)

포인터는 C++에서 메모리 관리와 데이터 구조를 효율적으로 다루기 위해 필수적으로 알아야 하는 개념입니다. 포인터를 사용하면 변수의 메모리 주소를 직접 다룰 수 있으며, 이는 성능 최적화와 메모리 절약에 큰 도움이 됩니다. 특히 대규모 소프트웨어 개발이나 시스템 프로그래밍에서는 포인터를 활용한 데이터 구조 (예: 링크드 리스트, 트리 등)가 자주 사용됩니다.

포인터의 개념을 이해하지 못하면, 메모리의 직접적인 조작이 불가능해지고, 이는 메모리 누수, 성능 저하, 프로그램 충돌 등의 문제를 초래할 수 있습니다. 따라서 포인터는 C++ 프로그래밍의 기초이자 필수적인 요소입니다.

2. 핵심 개념 설명

포인터는 변수의 메모리 주소를 저장하는 변수입니다. 변수를 가리키는 '지침서'와 같아서, 우리가 데이터를 저장한 위치를 쉽게 찾을 수 있게 해줍니다.

관련 용어 정리

용어설명
포인터메모리 주소를 저장하는 변수
참조포인터와 유사하지만, 메모리 주소를 직접 다루지 않음
주소 연산자변수의 메모리 주소를 가져오는 연산자 (&)
역참조 연산자포인터가 가리키는 메모리 주소의 값을 가져오는 연산자 (*)

비유하자면, 포인터는 집 주소를 가진 지도와 같습니다. 집(변수)이 어디에 있는지를 알려주는 주소(포인터)가 있어야 우리는 그 집을 쉽게 찾고 들어갈 수 있습니다.

3. 기본 코드 예제

아래는 포인터의 기본 사용법을 보여주는 코드입니다.

#include <iostream>
using namespace std;

int main() {
    int num = 42;             // 정수형 변수 num을 선언하고 42로 초기화
    int ptr = &num;         // ptr 포인터가 num의 주소를 가리키도록 설정

    cout << "num의 값: " << num << endl;           // num의 값을 출력
    cout << "num의 주소: " << &num << endl;        // num의 주소를 출력
    cout << "ptr이 가리키는 주소: " << ptr << endl; // ptr이 가리키는 주소를 출력
    cout << "ptr이 가리키는 값: " << ptr << endl; // ptr이 가리키는 주소의 값을 출력

    return 0;
}

실행 결과

num의 값: 42
num의 주소: 0x7ffc3c6b5c4c (주소는 시스템마다 다를 수 있음)
ptr이 가리키는 주소: 0x7ffc3c6b5c4c
ptr이 가리키는 값: 42

코드 한 줄씩 동작 설명

  1. int num = 42; - 정수형 변수 num을 선언하고 42로 초기화합니다.
  2. int* ptr = &num; - ptr이라는 포인터 변수를 선언하고, num의 주소를 저장합니다.
  3. cout << "num의 값: " << num << endl; - num의 값을 출력합니다.
  4. cout << "num의 주소: " << &num << endl; - num의 메모리 주소를 출력합니다.
  5. cout << "ptr이 가리키는 주소: " << ptr << endl; - ptr이 가리키는 주소를 출력합니다.
  6. cout << "ptr이 가리키는 값: " << *ptr << endl; - ptr이 가리키는 주소의 값을 출력합니다.
  7. 4. 실전 활용 예제

    예제 1: 함수에서 포인터 사용

    쇼핑몰에서 장바구니에 담긴 상품의 총 가격을 계산할 때, 포인터를 사용하여 가격을 업데이트할 수 있습니다.

    #include <iostream>
    using namespace std;
    
    void updatePrice(double price) {
        price += 10.0; // 가격에 10.0을 추가
    }
    
    int main() {
        double itemPrice = 100.0; // 상품 가격
        cout << "원래 가격: " << itemPrice << endl;
        updatePrice(&itemPrice);   // 가격 업데이트 함수 호출
        cout << "업데이트된 가격: " << itemPrice << endl; // 업데이트된 가격 출력
        return 0;
    }

    예제 2: 동적 메모리 할당

    사용자가 입력한 수만큼 배열을 생성할 때 포인터와 동적 메모리를 사용할 수 있습니다.

    #include <iostream>
    using namespace std;
    
    int main() {
        int n;
        cout << "배열 크기를 입력하세요: ";
        cin >> n;
    
        int* arr = new int[n]; // 동적 메모리 할당
        for (int i = 0; i < n; i++) {
            arr[i] = i + 1;     // 배열에 값 저장
        }
    
        cout << "배열 요소: ";
        for (int i = 0; i < n; i++) {
            cout << arr[i] << " "; // 배열 요소 출력
        }
        cout << endl;
    
        delete[] arr; // 동적 메모리 해제
        return 0;
    }

    5. 흔한 실수와 주의사항

  8. 초기화되지 않은 포인터 사용
  9. - 잘못된 코드:

         int ptr; // 초기화되지 않음
         cout << ptr; // 정의되지 않은 행동

    - 올바른 코드:

         int num = 42;
         int ptr = &num; // 초기화 후 사용
         cout << ptr; // 42가 출력됨
  10. 메모리 해제 누락
  11. - 잘못된 코드:

         int* arr = new int[5];
         // 배열 사용 후 메모리 해제 안 함

    - 올바른 코드:

         int* arr = new int[5];
         delete[] arr; // 메모리 해제
  12. 잘못된 포인터 연산
  13. - 잘못된 코드:

         int num = 10;
         int* ptr = &num;
         ptr++; // 잘못된 포인터 연산, ptr이 가리키는 주소를 넘어감

    - 올바른 코드:

         int num = 10;
         int ptr = &num; // ptr은 num을 가리킴
         cout << ptr; // 10 출력

    6. 정리

    • 포인터는 메모리 주소를 저장하는 변수로, 메모리 관리에 필수적입니다.
    • 포인터를 사용하면 함수에서 변수 값을 직접 수정할 수 있습니다.
    • 동적 메모리 할당과 같은 고급 기능을 활용할 수 있습니다.
    • 포인터 사용 시 초기화, 메모리 해제, 포인터 연산에 주의해야 합니다.

다음에 학습하면 좋은 주제: 참조(References), 동적 메모리 할당과 관리, 구조체(Structures).