포인터와 메모리

C와 C++의 포인터와 주소

이 레슨에서는 변수의 주소를 포인터에 저장하고, 포인터로 값에 접근해 원래 변수를 바꿉니다.

소개

포인터(pointer)는 다른 변수의 메모리 주소를 담는 변수입니다. & 연산자는 변수의 주소를 주고, * 연산자(역참조)는 가리키는 주소에 있는 값에 접근합니다. 포인터는 C와 C++에서 가장 중요한 개념 중 하나입니다.

핵심 정리

  • 포인터는 아직 존재하는 올바른 타입의 객체만 가리키거나 null이어야 합니다.
  • 할당한 메모리 영역은 정확히 한 번만 해제해야 합니다.
  • 어떤 함수가 메모리를 소유(ownership)하는지, 어떤 데이터는 읽기만 하는지(const) 분명히 하세요.

C와 C++ 코드 예제

C
실행 →
main.c
#include <stdio.h>

int main(void) {
    int score = 70;
    int *score_ptr = &score;
    *score_ptr += 5;
    printf("score=%d same-address=%s\n", score,
           score_ptr == &score ? "yes" : "no");
    return 0;
}
실행 결과
score=75 same-address=yes
C++
실행 →
main.cpp
#include <iostream>

int main() {
    int score = 70;
    int* score_ptr = &score;
    *score_ptr += 5;
    std::cout << "score=" << score << " same-address="
              << std::boolalpha << (score_ptr == &score) << '\n';
}
실행 결과
score=75 same-address=true

C와 C++ 비교

포인터 score_ptr에는 score의 주소가 들어 있으므로, *score_ptr += 5는 실제로 score 변수 자체에 5를 더해 70을 75로 만듭니다. score_ptr == &score 비교로 두 주소가 같다는 것을 확인할 수 있습니다. C++도 메모리 관리 없이 데이터에 접근만 하면 될 때는 원시 포인터(raw pointer)를 쓰지만, 변수가 절대 비어 있으면 안 될 때는 참조를 선호합니다.

C

메모리의 소유와 해제는 전적으로 프로그래머에게 달려 있습니다.

C++

컨테이너와 RAII가 객체의 수명이 끝날 때 자원을 자동으로 해제합니다.

연습 문제

두 버전을 모두 실행한 다음 코드를 바꿔 보면서 각 언어가 주는 안전성의 차이를 살펴보세요.

  • 널 포인터와 메모리 할당 실패 상황으로 테스트해 보세요.
  • AddressSanitizer와 UndefinedBehaviorSanitizer로 실행해 메모리 오류를 찾아보세요.
  • 어떤 포인터가 메모리를 소유하고 어떤 포인터는 읽기만 하는지 분명히 해 보세요.

챌린지로 연습하기

이 레슨에서 배운 내용으로 실제 문제를 풀어 보세요. 모든 챌린지는 브라우저에서 실행되며 즉시 테스트와 AI 리뷰를 받을 수 있습니다.

모든 챌린지