C++시작과 문법

포인터 기본

포인터 선언과 역참조, nullptr, 포인터 산술, 포인터와 참조의 차이, const 포인터 네 가지 조합을 정리합니다.

마지막 수정 2026년 3월 26일

기본 패턴

cpp
int value = 42;
int* ptr  = &value;   // &: 주소 연산자 — ptr에 value의 주소 저장

std::cout << ptr;     // 주소 출력 (예: 0x7ffee4a1c)
std::cout << *ptr;    // 역참조 — 42 출력
*ptr = 100;           // 역참조로 원본 수정 → value == 100

설명

포인터란

포인터는 다른 변수의 메모리 주소를 저장하는 변수입니다. * 타입 수식자로 선언하고, &로 주소를 얻고, *로 역참조합니다.

cpp
int  n   = 10;
int* p   = &n;   // p는 n의 주소를 저장
int** pp = &p;   // 포인터의 포인터도 가능

nullptr — 안전한 널 포인터

cpp
int* p = nullptr;   // 아무것도 가리키지 않음

if (p != nullptr) {
    std::cout << *p;  // 역참조 전에 항상 확인
}

// 0이나 NULL 대신 nullptr을 써야 타입 안전

화살표 연산자 →

포인터를 통해 구조체나 클래스 멤버에 접근할 때 사용합니다.

cpp
struct Point { int x, y; };

Point pt{3, 7};
Point* ppt = &pt;

std::cout << ppt->x;        // (*ppt).x 와 동일
ppt->y = 10;

포인터 산술

배열 순회에 사용됩니다. 포인터에 정수를 더하면 타입 크기만큼 이동합니다.

cpp
int arr[]{10, 20, 30, 40};
int* p = arr;                // 배열 이름은 첫 번째 요소의 포인터

std::cout << *(p + 1);       // 20
std::cout << *(p + 2);       // 30

for (int* it = arr; it != arr + 4; ++it) {
    std::cout << *it << " ";
}

const 포인터 — 네 가지 조합

cpp
int a = 1, b = 2;

int*       p1 = &a;   // 값도 주소도 변경 가능
const int* p2 = &a;   // 값 변경 불가, 주소는 변경 가능 (pointer-to-const)
int* const p3 = &a;   // 값 변경 가능, 주소는 변경 불가 (const pointer)
const int* const p4 = &a;  // 값도 주소도 변경 불가

// *p2 = 5;  ❌ 오류
p2 = &b;   // ✅ 주소 변경 가능
// p3 = &b; ❌ 오류
*p3 = 5;   // ✅ 값 변경 가능

포인터 vs 참조

포인터참조
nullptr 가능❌ (항상 유효한 객체)
재할당✅ 다른 변수 가리키기 가능❌ 한 번 바인딩 후 고정
문법*p, p->mr, r.m
주 사용처동적 메모리, 배열함수 인수, 반환값

빠른 정리

연산설명
&var변수의 주소 반환
*ptr포인터 역참조 (가리키는 값에 접근)
ptr->member포인터를 통한 멤버 접근
nullptr빈 포인터 표현 (0, NULL 대신 사용)
const int* p가리키는 값을 변경할 수 없음
int* const p포인터 자체(주소)를 변경할 수 없음

주의할 점

초기화하지 않은 포인터는 쓰레기 주소를 가집니다. 역참조하면 정의되지 않은 동작(UB)이 발생합니다. 선언 즉시 nullptr이나 유효한 주소로 초기화하세요.

delete 없이 new로 할당한 메모리를 포인터 변수가 가리키고 있을 때, 그 포인터를 잃어버리면 메모리 누수가 발생합니다. 현대 C++에서는 원시 포인터 대신 스마트 포인터 사용을 권장합니다.

참고 링크

1 sources