포인터와 메모리

C와 C++의 포인터 연산

이 레슨에서는 C의 포인터 연산과 C++의 반복자로 배열의 요소를 차례로 돌아봅니다.

소개

포인터에 1을 더하면 1바이트가 아니라 배열의 다음 요소로 이동합니다. 컴파일러가 타입의 크기에 맞춰 이동 거리를 계산하기 때문입니다. 그래서 포인터를 이용해 연속된 메모리 영역을 배열처럼 돌아볼 수 있습니다.

핵심 정리

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

C와 C++ 코드 예제

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

int main(void) {
    int values[] = {10, 20, 30, 40};
    int sum = 0;
    for (int *p = values; p < values + 4; ++p) sum += *p;
    printf("sum=%d distance=%td\n", sum, (values + 4) - values);
    return 0;
}
실행 결과
sum=100 distance=4
C++
실행 →
main.cpp
#include <iostream>
#include <vector>

int main() {
    std::vector values{10, 20, 30, 40};
    int sum = 0;
    for (auto it = values.begin(); it != values.end(); ++it) sum += *it;
    std::cout << "sum=" << sum << " distance="
              << std::distance(values.begin(), values.end()) << '\n';
}
실행 결과
sum=100 distance=4

C와 C++ 비교

반복문은 포인터 p가 첫 번째 요소를 가리키는 데서 시작해 p가 values + 4 위치에 이를 때까지 나아갑니다. 단계마다 *p가 현재 값을 꺼내 합계에 더합니다. 포인터 연산은 같은 배열 안이나 마지막 요소 바로 다음 위치까지만 유효합니다. C++에서는 반복자로 여러 종류의 컨테이너를 같은 방식으로 돌아볼 수 있습니다.

C

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

C++

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

연습 문제

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

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

챌린지로 연습하기

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

모든 챌린지