학습
C++ 포인터 (Pointers)
C++ 포인터 (Pointers) — 초급
포인터 (Pointers)
1. 도입 (왜 배워야 하는가)
포인터는 C++에서 메모리 관리와 데이터 구조를 효율적으로 다루기 위해 필수적으로 알아야 하는 개념입니다. 포인터를 사용하면 변수의 메모리 주소를 직접 다룰 수 있으며, 이는 성능 최적화와 메모리 절약에 큰 도움이 됩니다. 특히 대규모 소프트웨어 개발이나 시스템 프로그래밍에서는 포인터를 활용한 데이터 구조 (예: 링크드 리스트, 트리 등)가 자주 사용됩니다.
포인터의 개념을 이해하지 못하면, 메모리의 직접적인 조작이 불가능해지고, 이는 메모리 누수, 성능 저하, 프로그램 충돌 등의 문제를 초래할 수 있습니다. 따라서 포인터는 C++ 프로그래밍의 기초이자 필수적인 요소입니다.
2. 핵심 개념 설명
포인터는 변수의 메모리 주소를 저장하는 변수입니다. 변수를 가리키는 '지침서'와 같아서, 우리가 데이터를 저장한 위치를 쉽게 찾을 수 있게 해줍니다.
관련 용어 정리
| 용어 | 설명 |
|---|---|
| 포인터 | 메모리 주소를 저장하는 변수 |
| 참조 | 포인터와 유사하지만, 메모리 주소를 직접 다루지 않음 |
| 주소 연산자 | 변수의 메모리 주소를 가져오는 연산자 (&) |
| 역참조 연산자 | 포인터가 가리키는 메모리 주소의 값을 가져오는 연산자 (*) |
비유하자면, 포인터는 집 주소를 가진 지도와 같습니다. 집(변수)이 어디에 있는지를 알려주는 주소(포인터)가 있어야 우리는 그 집을 쉽게 찾고 들어갈 수 있습니다.
3. 기본 코드 예제
아래는 포인터의 기본 사용법을 보여주는 코드입니다.
#include <iostream>
using namespace std;
int main() {
int num = 42; // 정수형 변수 num을 선언하고 42로 초기화
int ptr = # // 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
코드 한 줄씩 동작 설명
int num = 42;- 정수형 변수num을 선언하고 42로 초기화합니다.int* ptr = #-ptr이라는 포인터 변수를 선언하고,num의 주소를 저장합니다.cout << "num의 값: " << num << endl;-num의 값을 출력합니다.cout << "num의 주소: " << &num << endl;-num의 메모리 주소를 출력합니다.cout << "ptr이 가리키는 주소: " << ptr << endl;-ptr이 가리키는 주소를 출력합니다.cout << "ptr이 가리키는 값: " << *ptr << endl;-ptr이 가리키는 주소의 값을 출력합니다.- 초기화되지 않은 포인터 사용
- 메모리 해제 누락
- 잘못된 포인터 연산
- 포인터는 메모리 주소를 저장하는 변수로, 메모리 관리에 필수적입니다.
- 포인터를 사용하면 함수에서 변수 값을 직접 수정할 수 있습니다.
- 동적 메모리 할당과 같은 고급 기능을 활용할 수 있습니다.
- 포인터 사용 시 초기화, 메모리 해제, 포인터 연산에 주의해야 합니다.
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. 흔한 실수와 주의사항
- 잘못된 코드:
int ptr; // 초기화되지 않음
cout << ptr; // 정의되지 않은 행동
- 올바른 코드:
int num = 42;
int ptr = # // 초기화 후 사용
cout << ptr; // 42가 출력됨
- 잘못된 코드:
int* arr = new int[5];
// 배열 사용 후 메모리 해제 안 함
- 올바른 코드:
int* arr = new int[5];
delete[] arr; // 메모리 해제
- 잘못된 코드:
int num = 10;
int* ptr = #
ptr++; // 잘못된 포인터 연산, ptr이 가리키는 주소를 넘어감
- 올바른 코드:
int num = 10;
int ptr = # // ptr은 num을 가리킴
cout << ptr; // 10 출력
6. 정리
다음에 학습하면 좋은 주제: 참조(References), 동적 메모리 할당과 관리, 구조체(Structures).