C++ 포인터: 단순한 주소가 아닌 메모리 제어의 핵심
포인터는 단순히 "주소를 저장하는 변수"로 시작하지만, C++에서는 이보다 훨씬 깊은 의미를 가집니다. 이번 글에서는 포인터의 기본을 넘어, 메모리 모델, 포인터 산술, const 포인터, 함수 포인터, 동적 할당 관리까지 보다 심도 있게 다룹니다.
포인터는 메모리 모델 그 자체
C++은 하드웨어와 밀접하게 맞닿아 있는 언어입니다. 포인터를 이해한다는 것은 결국 메모리의 구조 자체를 이해한다는 것과 같습니다. 모든 변수는 물리적 메모리 어딘가에 주소를 가지고 있고, 포인터는 그 주소를 직접 다룰 수 있게 합니다.
int x = 42;
int* p = &x;
위에서 p는 스택 메모리 상의 변수 x의 주소를 저장합니다. 이 주소를 역참조(*p)하면 x의 값을 읽거나 수정할 수 있습니다.
포인터 산술(pointer arithmetic)
포인터는 단순히 주소만 저장하는 것이 아니라, 자료형을 알고 있는 주소입니다. 그래서 포인터 간 연산은 단순 주소값 계산이 아니라 타입에 따라 자동으로 크기를 고려합니다.
int arr[5] = {10, 20, 30, 40, 50};
int* p = arr; // 배열 이름은 첫 원소 주소
p++; // 다음 int로 이동 (주소 + sizeof(int))
이 때 p++는 실제 주소값에 4바이트(int 크기)만큼 증가하는 연산입니다. 포인터 산술은 정적 배열뿐 아니라 동적 메모리에서도 강력한 순회 도구가 됩니다.
const 포인터와 포인터 상수
const의 위치에 따라 포인터의 의미는 달라집니다:
const int* p: 가리키는 값을 수정 불가 (읽기 전용 데이터)int* const p: 포인터가 다른 주소를 가리키는 것 불가 (고정된 주소)const int* const p: 값도 수정 불가, 주소도 변경 불가 (완전 상수화)
동적 메모리와 포인터
정적 메모리(스택)를 넘어서는 유연성을 제공하는 것이 동적 메모리 할당입니다.
int* p = new int(42);
*p = 100;
delete p;
new로 할당한 메모리는 delete로 반드시 해제해야 합니다. 이 과정을 생략하거나 실수하면 메모리 누수(leak)가 발생합니다.
C++11 이후 등장한 스마트 포인터는 이런 관리 부담을 크게 줄여줍니다.
std::unique_ptr<int> p = std::make_unique<int>(42);
스마트 포인터는 포인터를 객체처럼 관리하여 RAII 패턴에 따라 메모리 안전성을 크게 높여줍니다.
함수 포인터: 코드 주소도 포인터다
포인터는 데이터뿐 아니라 함수의 주소도 가리킬 수 있습니다.
int add(int a, int b) { return a + b; }
int (*fp)(int, int) = add;
int result = fp(3, 4); // 함수 호출
함수 포인터는 콜백 구현, 테이블 기반 디스패치 등에 유용하게 활용됩니다. 특히 STL의 std::function과 결합하면 보다 현대적인 형태로 일반화할 수 있습니다.
다중 포인터 (이중 포인터)
포인터를 가리키는 포인터도 가능합니다:
int x = 10;
int* p = &x;
int** pp = &p;
**pp = 20; // 결국 x의 값을 바꿈
다중 포인터는 다차원 동적 배열, 복잡한 자료구조, 라이브러리 함수 인터페이스 등에서 종종 활용됩니다.
포인터의 위험성과 강력함
- Dangling Pointer: 삭제된 메모리를 계속 참조
- Memory Leak: 할당 후 해제를 잊음
- Buffer Overflow: 배열 경계 초과 접근
포인터는 C++의 가장 위험한 도구 중 하나입니다. 하지만 동시에, 이 저수준 제어력을 통해 C++이 여전히 시스템 프로그래밍 최강의 언어로 남아있게 합니다.
감사합니다.
'프로그래밍 > C\C++' 카테고리의 다른 글
| C/C++ 참조자(reference) 내용 정리 (4) | 2025.06.19 |
|---|---|
| [Effective C++ 정리 #9] 생성자에서 가상 함수 호출 문제 및 해결 방법 (4) | 2025.06.19 |
| [Effective C++ 정리 #8] 소멸자에서 예외 처리 시 발생할 수 있는 문제 및 해결 방안 (2) | 2025.06.18 |
| [Effective C++ 정리 #7] 이걸 안 하면 메모리 누수! 소멸자는 왜 virtual이어야 할까? (4) | 2025.06.17 |
| [Effective C++ 정리 #6] 복사 금지! 컴파일러가 몰래 만든 함수 차단 방법 (0) | 2025.06.16 |