C++ 포인터 완전 정복: 개념, 예제, 실전 활용
포인터란?
C++에서 포인터는 다른 변수의 메모리 주소를 저장하는 변수입니다. 포인터의 타입은 가리키는 데이터의 타입과 일치해야 합니다. 예를 들어 int*는 int 객체의 주소만 저장할 수 있습니다.
포인터는 프로그램이 메모리의 데이터를 직접 조작할 수 있게 하여 효율적인 자료구조, 동적 할당, 호출-참조(call-by-reference) 의미론을 가능하게 합니다.
메모리 주소 이해
모든 변수는 RAM의 고유한 위치에 할당됩니다. 참조 연산자 &가 그 주소를 가져옵니다. 변수 x에 대해 &x는 메모리 위치를 산출합니다.
포인터 선언 문법
선언은 다음 패턴을 따릅니다:
datatype *pointer_name;
- datatype – 포인터가 가리키는 데이터의 기본 타입
- pointer_name – 포인터 변수 식별자
- 애스터리스크는 변수가 포인터임을 나타냄
예제:
int *p; // int 포인터
double *d; // double 포인터
char *c; // char 포인터
참조(&) vs 역참조(*)
& 연산자는 변수의 주소를 주고, * 연산자는 그 주소에 저장된 값을 가져옵니다.
#include <iostream>
using namespace std;
int main() {
int x = 27;
int *ip = &x;
cout << "Value of x: " << x << endl;
cout << "Address of x: " << ip << endl;
cout << "Value via pointer: " << *ip << endl;
return 0;
}
출력:
Value of x: 27
Address of x: 0x7ffeefbff5ac
Value via pointer: 27
포인터와 배열
배열 이름은 첫 번째 요소에 대한 포인터로 변환됩니다. 따라서:
int arr[5];
int *p = arr; // 올바름
int *q = &arr; // 잘못됨 – &arr은 전체 배열의 주소이지 첫 번째 요소가 아님
포인터로 배열 순회:
#include <iostream>
using namespace std;
int main() {
int *p;
int arr[] = {10, 34, 13, 76, 5, 46};
p = arr;
for (int i = 0; i < 6; ++i) {
cout << *p++ << endl;
}
return 0;
}
출력:
10
34
13
76
5
46
널 포인터
포인터가 유효한 대상을 가지지 않을 때는 NULL (또는 C++11 이후 nullptr)로 초기화해야 합니다. 이는 의도치 않은 역참조를 방지합니다.
#include <iostream>
using namespace std;
int main() {
int *ip = nullptr;
cout << "ip = " << ip << endl; // 0 출력
return 0;
}
함수에서 포인터 사용
함수에 포인터를 전달하면 함수가 원래 변수를 수정할 수 있습니다. 이 기법은 호출-참조를 구현합니다.
#include <iostream>
using namespace std;
void modify(int *p1, int *p2) {
*p1 = 10;
*p2 = 11;
}
int main() {
int a = 5, b = 5;
cout << "Before: a=" << a << ", b=" << b << endl;
modify(&a, &b);
cout << "After: a=" << a << ", b=" << b << endl;
return 0;
}
출력:
Before: a=5, b=5
After: a=10, b=11
포인터의 이점
- 고성능 코드를 위한 직접 메모리 접근
- 단일 함수 호출로 여러 변수 수정 가능
- 동적 메모리 할당 및 해제 (예:
new / delete)
- 연결 리스트, 트리, 그래프 같은 복잡한 자료구조의 기반
- 객체 지향 설계에서 효율적인 자원 공유와 다형성 지원
빠른 요약
- 포인터는 다른 변수의 주소를 저장합니다.
- 주소 얻기엔
&, 역참조엔 * 사용
- 배열 이름은 첫 번째 요소 포인터로 변환됨
- 미사용 포인터는
nullptr로 초기화
- 함수에 포인터 전달로 제자리 수정 가능
- 포인터는 동적 메모리 관리와 효율적 자료구조 가능하게 함