포인터 (Pointer)
포인터(Pointer)는 메모리의 주소(Address)를 저장하는 변수이다.
일반 변수는 값을 저장하지만,
int a = 10;
포인터는 주소를 저장한다.
int* p = &a;
변수는 메모리 공간이다
int a = 10;
이 코드를 실행하면 메모리 어딘가에 공간이 생성되고 그 공간은
메모리 내 변수의 위치정보를 알리기 위한 주소를 가진다.
예시:
주소 변수 값
1000 a 10
- 변수 이름 : a
- 주소 : 1000
- 값 : 10
실제 사용될 때의 주소의 형태는 다르지만 이해를 위해 주소를 1000 이라고 가정한다.
컴퓨터는 주소를 사용한다
사람이 적을때
a = 20;
컴퓨터가 하는 동작
1000번지에 저장된 값을 20으로 변경
즉, 컴퓨터 입장에서는 변수 이름보다 주소가 더 중요하다.
포인터 선언
int* p;
의 의미는
정수(int)의 주소를 저장할 수 있는 포인터 변수 p
이다.
주소 저장하기
int a = 10;
int* p = &a;
여기서
&a
는
a의 주소
를 의미한다.
예시:
주소 변수 값
1000 a 10
2000 p 1000
메모리 구조
p
↓
1000
↓
a
↓
10
포인터 p는 a의 주소를 저장하고 있다.
& 연산자
주소를 가져오는 연산자이다.
int a = 10;
cout << &a;
출력:
0000007FF6D1...
실제 메모리 주소가 출력된다.
* 연산자 (역참조)
포인터가 가리키는 주소의 실제 값에 접근하는 연산자이다.
int a = 10;
int* p = &a;
cout << *p;
출력:
10
왜 10이 출력될까?
주소 변수 값
1000 a 10
2000 p 1000
p는 1000을 저장하고 있다.
*p
는
1000번지에 있는 값
을 의미한다.
즉,
*p == a
와 같은 결과를 얻는다.
포인터로 값 변경하기
int a = 10;
int* p = &a;
*p = 20;
실행 후
주소 변수 값
1000 a 20
2000 p 1000
결과:
cout << a;
출력:
20
왜 값이 바뀔까?
*p = 20;
의 의미는
1000번지에 있는 값을 20으로 변경
하는 것이다.
즉,
a = 20;
과 동일한 효과를 가진다.
Call By Value
일반적인 함수 호출은 값을 복사한다.
void SetValue(int x)
{
x = 20;
}
int main()
{
int a = 10;
SetValue(a);
}
함수 호출 시
SetValue(a);
는 실제로
int x = a;
와 비슷한 동작을 한다.
메모리 구조
main Stack Frame
주소 변수 값
1000 a 10
함수 호출 후
main Stack Frame
주소 변수 값
1000 a 10
func Stack Frame
주소 변수 값
2000 x 10
x는 a의 복사본이다.
x = 20;
을 실행하면
a = 10
x = 20
이 된다.
서로 다른 변수이므로 a는 변경되지 않는다.
이것을 Call by Value(값에 의한 호출)이라고 한다.
포인터를 사용하는 이유
원본 데이터를 직접 관리하는 것이 가능하기 때문이다.
void SetValue(int* p)
{
*p = 20;
}
int main()
{
int a = 10;
SetValue(&a);
}
함수 호출
SetValue(&a);
실행 시
p = &a;
가 된다.
메모리 구조
main Stack Frame
주소 변수 값
1000 a 10
func Stack Frame
주소 변수 값
2000 p 1000
*p = 20;
실행
1000번지 값을 20으로 변경
결과
a == 20
원본 데이터가 수정된다.
Call By Reference
포인터 말고도 원본 데이터를 수정하는 방법이 있다.
void SetValue(int& x)
{
x = 20;
}
int main()
{
int a = 10;
SetValue(a);
}
결과:
a == 20
참조자란?
int a = 10;
int& ref = a;
참조자는 새로운 변수가 아니다.
기존 변수의 별명(Alias)이다.
예시:
ref = 20;
실행 후
a == 20
이 된다.
ref와 a는 같은 데이터를 바라보기 때문이다.
포인터와 참조자의 차이
포인터
void func(int* p)
{
*p = 20;
}
func(&a);
참조자
void func(int& x)
{
x = 20;
}
func(a);
비교
| 구분 | 포인터 | 참조자 |
|---|---|---|
| 선언 | int* p |
int& ref |
| 주소 저장 | O | X |
| nullptr 가능 | O | X |
| 재할당 가능 | O | X |
| 사용법 | *p |
ref |
| 문법 | 복잡 | 간단 |
Call By Value / Address / Reference 비교
Call By Value
void func(int x)
- 값 복사
- 원본 수정 불가
Call By Address
void func(int* p)
- 주소 전달
- 원본 수정 가능
- 포인터 사용
Call By Reference
void func(int& x)
- 참조 전달
- 원본 수정 가능
- 문법이 간단함
핵심 정리
포인터는 메모리의 주소를 저장하는 변수이다.
int a = 10;
int* p = &a;
주소 얻기
&a
값 접근하기
*p
값 수정하기
*p = 20;
Call By Value는 값을 복사하기 때문에 원본이 변경되지 않는다.
func(a);
Call By Address는 주소를 전달하여 원본을 수정할 수 있다.
func(&a);
Call By Reference는 참조자를 사용하여 원본을 수정할 수 있다.
func(a);
포인터는 단순히 함수 인자 전달뿐 아니라
- 동적 할당 (
new) - 배열
- 문자열
- 연결 리스트
- 트리
- 스마트 포인터
- 언리얼 엔진 객체 관리
등의 기반이 되는 매우 중요한 개념이다.
'c++ > 기초' 카테고리의 다른 글
| #define 0 NULL (0) | 2026.06.02 |
|---|---|
| 참조자(Reference) (0) | 2026.05.31 |
| 매크로 (0) | 2026.05.31 |
| 정적 변수 (0) | 2026.05.29 |
| 오버로딩 (0) | 2026.05.29 |