C언어 포인터 기초

🔥 매회 출제 (priority 3)

🌱 왜 배우나

친구에게 “우리 집에 오렴”이라고 말로만 하면, 친구는 길을 모른다. 그런데 “서울시 강남구 ○○로 12번지”라고 주소를 알려 주면, 친구가 직접 찾아가서 현관 물건까지 바꿔 놓을 수 있다.

C언어의 포인터가 바로 이 “주소”다. 값을 통째로 복사해서 전달하는 대신, 값이 저장된 위치만 알려 준다. 그러면 그 위치에 있는 원본을 직접 읽거나 고칠 수 있다. 크기가 큰 데이터도 주소 한 줄만 넘기면 되니 낭비가 없다. 이 이유로 포인터가 만들어졌다.

📖 핵심 개념

포인터(Pointer)는 메모리 주소를 담는 변수다. 변수는 값을 넣어 두는 이름표 붙은 상자라고 보면 된다. 메모리 주소는 컴퓨터가 그 상자를 놓아둔 자리 번호다. 즉 포인터는 “어디에 있는지”를 기억하는 특별한 변수다.

포인터 선언에는 별표 *를 붙인다. int *p;는 “정수가 들어 있는 자리의 주소를 담을 p”라는 뜻이다.

주소를 얻을 때는 주소 연산자 &를 쓴다. &a는 “변수 a가 놓인 자리 번호를 알려 줘”라는 뜻이다.

포인터가 가리키는 자리의 값을 꺼낼 때는 역참조 연산자 *를 쓴다. *p는 “p가 가리키는 자리로 가서 값을 꺼내 와”라는 뜻이다. 왼쪽에 쓰면 그 자리의 값을 바꾼다는 뜻이 된다.

포인터를 쓰면 다른 변수의 값을 간접적으로 읽고 고칠 수 있다. 이것이 핵심 기능이다.

🔍 시각화

변수 a 와 포인터 p 의 관계:

        메모리
주소     ┌─────────┐
0x100   │  a = 10  │ ◀─── 변수 a 가 여기 저장됨
        ├─────────┤
0x200   │ p = 0x100│ ◀─── 포인터 p 는 a 의 주소를 담고 있음
        └─────────┘

  &a  → 0x100   (a 의 주소를 알려 줘)
  *p  → 10      (p 가 가리키는 곳의 값을 꺼내 와)
  *p = 20       (p 가 가리키는 곳의 값을 20 으로 바꿔)
  → 결과적으로 a 도 20 이 됨

↔️ 이웃 개념 구분

  • & vs *: &는 “변수의 주소를 알려 줘”. *는 “그 주소로 가서 값을 꺼내거나 바꿔”.
  • 일반 변수 vs 포인터: 일반 변수는 값 자체를 담음. 포인터는 다른 변수가 놓인 자리(주소)를 담음.

🔑 핵심 용어

  • 포인터 선언: int *p; — 정수가 들어 있는 자리의 주소를 담을 변수 p를 만든다. 이 시점에는 아직 아무 곳도 가리키지 않는다
  • 주소 연산자(&): p = &a; — 변수 a가 놓인 메모리 자리 번호를 p에 저장
  • 역참조 연산자(*): *p — p가 가리키는 자리에 저장된 값에 접근
  • 포인터와 배열의 관계: 배열 이름은 첫 번째 원소의 주소와 같다. arr[i]*(arr+i)와 같은 뜻이다
  • NULL 포인터: 아무 곳도 가리키지 않는 포인터. 초기화하지 않고 사용하면 프로그램이 엉뚱한 자리를 건드려 오류가 난다

✅ 스스로 가르쳐보기

포인터라는 말을 처음 듣는 친구에게 설명한다면 어떻게 말하시겠어요? 편지 주소, 사물함 번호, 택배 송장 같은 일상 비유 하나로 한 문장 정의를 만들어 보세요.

체크포인트 — 아래를 말로 풀어 설명할 수 있는지 확인해 보세요.

  • &*가 각각 무슨 일을 하는지
  • *p = 20;을 실행하면 왜 변수 a의 값까지 바뀌는지
  • 배열 이름이 포인터처럼 쓰이는 이유
  • NULL 포인터를 그대로 사용하면 왜 위험한지

🎯 기출 포인트

C언어 포인터는 실기 단골이다. &*의 역할을 헷갈리면 한 문제를 통째로 놓친다. 자주 나오는 패턴은 세 가지다. 첫째, 포인터로 두 값을 맞바꾸는 swap 코드. 둘째, 배열과 포인터의 관계(*(arr+i) == arr[i]). 셋째, 이중 포인터(**pp) 출력 추적. 코드를 따라갈 때는 변수 이름, 주소, 현재 값을 표로 정리하며 한 줄씩 읽는다.

🔗 연결 개념