본문 바로가기
카테고리 없음

C언어 포인터 개념 정리

by erase-jeong 2025. 7. 13.

 

정보처리기사 실기를 공부하면서

시험범위 내에서 가장 어려운 부분은 C언어 포인터 부분이라고 생각되서,

이번기회로 정리 겸 복습하는 시간을 가졌습니다.

 

 

1. 포인터란?

포인터 : 주소를 저장하는 변수

 

 

예를 들어 정수형 변수 x를 선언하면, 컴퓨터의 메모리(RAM) 공간 중 일부가 x를 저장하기 위해 할당됩니다.

예를 들어, x가 저장된 메모리 주소가 0x0010이라고 가정해봅시다.

이때 변수 x의 주소값을 저장하려면 포인터가 필요합니다.
즉, x의 주소를 저장하는 변수가 포인터입니다.

 

 

int *p=&x;

 

 

여기서 p는 x의 주소를 저장하는 포인터이며, *p를 통해 x의 값을 간접적으로 접근하거나 수정할 수 있습니다.

 

 


 

2. 포인터는 어떻게 사용되는가?

 

포인터는 '주소를 저장하는 변수' 인 만큼 주소를 통해서 변수에 직접 접근 합니다.

 

일반 변수는 이름으로 접근하지만, 포인터는 메모리 주소(&x)를 저장하여, 해당위치의 값을 읽고 쓸 수 있다.

int x=5;
int *p=&x; //p에 x의 주소 저장
*p=10; //p가 가리키는 메모리에 10을 저장 => x값이 10로 변경

 

&가 붙으면 주소를 의미하는 것으로  &x는 x의 주소를 의미한다.

 

 

코드를 기반으로 포인터가 어떻게 작동하는지 알아보자.

 

1) 변수 선언

int x=5;

 

4바이트 크기의 변수 x를 선언하고, 그 공간에 값 5를 저장합니다.

 

 


 

2) 포인터 선언

int *p=&x; //p에 x의 주소 저장

 

 

  • int *p → “정수형 변수를 가리키는 포인터” p를 선언
  • &x → 변수 x의 메모리 주소 (예: 0x0010)
  • p = &x → 포인터 p의 메모리 셀에 x의 주소를 저장
  • 결과적으로, p는 “x가 위치한 메모리”를 가리키는 변수가 됩니다.

 

 

cf)

< 포인터에 자료형을 명시하는 이유 >

메모리에서 각 기본형 변수는 크기가 다릅니다.

  • int a→ 4 byte
  • char b → 1 byte
  • double c → 8 byte

역참조 시 읽기/쓰기 범위 결정

시작주소는 알고있지만, a는 4byte를 읽어야 하고, b는 1byte, c는 8byte를 읽어야 하는지,모르기에 포인터에도 자료형을 명시한다.

 

ex.

int *ptr_a=&a;

char *ptr_b=&b;

double *ptr_c=&c;

 


 

3)

*p=10; //p가 가리키는 메모리에 10을 저장 => x값이 10으로 변경

 

 

 

 

  • p 자체를 읽으면 → 0x0010 (주소값)
  • *p 연산은 → “p가 가리키는 주소(0x0010)의 메모리 셀
  • *p = 10; → p가 가리키는 위치에 10을 저장 ⇒ x의 값이 10으로 변경

 

 

 

 

3. 값 전달 vs 주소 전달: 포인터가 필요한 이유

값이 전달되는 방식에는 Call by Value (값 복사), Call by Reference (주소 전달) 가 있다.

 

Call by Value (값 복사)

 

  • 가장 기본적인 함수 호출 방식입니다.
  • 함수에 값의 복사본이 전달되므로, 함수 안에서 값을 바꾸더라도 원래 변수에는 아무 영향이 없습니다.

 

Call by Reference (주소 전달)

  • 포인터를 통해 변수의 메모리 주소 자체를 함수에 넘기는 방식입니다.
  • 함수 내부에서 포인터를 사용해 원본 데이터를 직접 수정할 수 있습니다.
  • 그래서 함수 안에서 변경한 값이 함수 밖에서도 반영됩니다

 

→ 원본 변수를 함수 내에서 바꾸고 싶다면, 반드시 포인터(주소 전달)를 사용해야 합니다.

 

 

(1) Call by Reference — 포인터를 이용한 값 변경

#include <stdio.h>

//두 변수의 값을 서로 변환하는 포인터 함수
void swap(int *x, int *y){
    //포인터는 *x
    //int 형의 어떠한 값을 가리키는 포인터 x를 만들었다
    int temp;
    temp=*x; //포인터 x가 가리키는 위치의 값을 넣어줌
    *x=*y; 
    *y=temp;
}

int main(void)
{
    int x=1;
    int y=2;
    swap(&x,&y);
    printf("x=%d\ny=%d\n",x,y);
    return 0;
}

 

출력결과

 

함수가 x, y의 주소를 받아 원본 값 자체를 바꾸었습니다.

 


 

 

(2) Call by Value — 포인터 없이 값만 넘긴 경우

#include <stdio.h>

//포인터를 이용하지 않고 바꿀 경우
void swap(int x, int y){
    int temp;
    temp=x; 
    x=y; 
    y=temp;
}

int main(void)
{
    int x=1;
    int y=2;
    swap(x,y);
    printf("x=%d\ny=%d\n",x,y);
    return 0;
}

 

출력결과

 

 

swap() 함수 안에서는 값이 바뀌었지만, main 함수의 x, y는 그대로입니다.
이유는 단순히 복사본만 바뀌었기 때문입니다.