C언어 | 포인터(Pointer)

설탕·2024년 3월 31일
0
post-thumbnail

주소와 포인터

주소

주소는 변수가 할당된 메모리 공간의 시작 주소를 의미한다. 시작 주소를 알면 그 위치부터 변수의 크기만큼 메모리를 사용할 수 있다. 주소는 주소 연산자 &를 사용해서 구한다.

포인터

포인터는 변수의 메모리 주소를 저장하는 변수다. 선언할 때는 변수 앞에 간접 참조 연산자(=포인트 연산자) *를 붙인다.
포인터를 선언할 때 주소 위치에 있는 변수의 자료형으로 선언해야 한다.

#include <stdio.h>

int main(void)
{
  int a; // 일반 변수 선언
  int *pa; // 포인터 선언

  pa = &a; // 포인터에 a의 주소 대입
  *pa = 10; // 포인터로 변수 a에 10 대입

  printf("포인터로 a 값 출력: %d\n", *pa); // 포인터로 a 값 출력: 10
  printf("변수명으로 a 값 출력: %d\n", a); // 변수명으로 a 값 출력: 10
  
  return 0;
}

포인터 pa는 변수 a가 메모리 어디에 할당되었는지 그 주소를 저장하는데, 이때 pa가 a를 가리킨다고 표현한다.

pa → a // 포인터 pa는 변수 a를 가리킨다!

주소와 포인터의 차이

  • 주소: 변수에 할당된 메모리 저장 공간의 시작 주소 값 자체
  • 포인터: 그 값을 저장하는 또 다른 메모리 공간

따라서 특정 변수의 주소 값은 바뀌지 않지만, 포인터는 다른 주소를 대입해 그 값을 바꿀 수 있다. 즉 주소는 상수고 포인트는 변수다.

주소와 포인터의 크기

포인터의 크기는 주소의 크기와 같다.
모든 주소와 포인터는 가리키는 자료형과 상관없이 그 크기가 같다.
sizeof 연산자를 이용해서 주소와 포인터의 크기를 확인할 수 있다.

#include <stdio.h>

int main(void)
{
  char ch;
  int in;
  double db;

  char *pc = &ch;
  int *pi = &in;
  double *pd = &db;

  printf("char형 변수의 주소 크기: %lu\n", sizeof(&ch)); // 8
  printf("int형 변수의 주소 크기: %lu\n", sizeof(&in)); // 8
  printf("double형 변수의 주소 크기: %lu\n", sizeof(&db)); // 8

  printf("char형 *포인터의 크기: %lu\n", sizeof(pc)); // 8
  printf("int형 *포인터의 크기: %lu\n", sizeof(pi)); // 8
  printf("double형 *포인터의 크기: %lu\n", sizeof(pd)); // 8

  printf("char형 *포인터가 가리키는 변수의 크기: %lu\n", sizeof(*pc)); // 1
  printf("int형 *포인터가 가리키는 변수의 크기: %lu\n", sizeof(*pi)); // 4
  printf("double형 *포인터가 가리키는 변수의 크기: %lu\n", sizeof(*pd)); // 8

  return 0;
}

포인터는 언제 사용할까?

포인터를 사용하면 함수 간에 효과적으로 데이터를 공유할 수 있다.
다음 경우에는 포인터가 반드시 필요하다.

  • 임베디드 프로그래밍을 할 때 메모리에 직접 접근하는 경우
  • 동적 할당한 메모리를 사용하는 경우

도전 실전 예제

미니 정렬 프로그램

키보드로 실수 3개를 입력한 후 큰 숫자부터 작은 숫자로 정렬한 뒤 출력하는 프로그램을 작성합니다. 다음 코드와 출력 결과를 참고해 line_up 함수를 작성하세요. line_up 함수에는 이미 정의된 swap 함수를 호출해 구현하세요.

입출력 예시

실수값 3개 입력: 2.7 1.5 3.4
정렬된 값 출력: 3.4, 2.7, 1.5

풀이

#include <stdio.h>

void swap(double *pa, double *pb);
void line_up(double *maxp, double *midp, double *minp);

int main(void)
{
  double max, mid, min;

  printf("실수값 3개 입력: ");
  scanf("%lf%lf%lf", &max, &mid, &min);
  line_up(&max, &mid, &min);
  printf("정렬된 값 출력: %.1lf, %.1lf, %.1lf\n", max, mid, min);

  return 0;
}

void swap(double *pa, double *pb)
{
  double temp;

  temp = *pa;
  *pa = *pb;
  *pb = temp;
}

void line_up(double *maxp, double *midp, double *minp)
{
  // 구현한 부분 - 다 한 번씩 비교하기!
  if (*maxp < *midp) swap(maxp, midp);
  if (*midp < *minp) swap(midp, minp);
  if (*maxp < *midp) swap(maxp, midp);
}

참고
GeeksforGeeks - Features and Use of Pointers in C/C++

profile
공부 기록

0개의 댓글