[TIL/크래프톤 정글9기] 33일차(C언어 포인터)

blueprint·2025년 6월 13일

크래프톤정글9기

목록 보기
28/55

포인터

포인터의 정의와 사용

  • 변수를 선언하는 것은 메모리에 기억공간을 할당하는 것임, 할당된 이후에는 변수명으로 그 기억공간을 사용
cheoli = 10;  // 할당된 기억공간에 10을 저장
metel = cheoli; // cheoli의 값을 다른 기억공간에 복사
  • 할당된 기억공간을 사용하는 방법에는 변수명 외에 메모리의 실제 주소값을 사용하는 것이다. 이 주소값을 포인터라고 한다.

포인터란 무엇인가?

  • 메모리에는 바이트 단위로 그 위치를 식별할 수 있는 물리적인 주고값이 있다.
  • 변수를 선언하면 그 자료형의 크기만큼 메모리에 연속된 바이트의 기억공간 할당되는데
    그 첫번쨰 바이트의 주소값이 포인터
  • 포인터를 사용하여 4바이트의 기억공간에 값을 저장하거나 저장된 값을 꺼내어 사용 가능

포인터를 구하자[주소연산자(&) -> 주소 읽기 연산자]

  • 특정 변수의 포인터를 구하기 위해서는 주소연산자(&. Anpersand) 사용

포인터는 특정 자료형을 가리킨다

  • 포인터에는 자신이 어떤 자료형으로부터 만들어졌는지에 대한 정보를 가지고 있다.
  • 포인터가 특정 자료형에 대한 정보를 가지고 있다는 것을 간단히 표현할 때 "가리킨다"라 한다.
  • 포인터를 통해 기억공간을 사용하기 위해서 참조연산자(*, Asterisk) 사용
char ch;
int in;
double db;
*&ch = 'P';
*&in = 100;
*&db = 3.14;
printf("%c\n", ch);  // 출력 P
printf("%c\n", in);  // 출력 100
printf("%lf\n", db); // 출력 3.140000
  • 기억공간을 사용하는 것과 값을 사용하는 것은 대입연산자의 어디에 위치하느냐에 따라 결정된다.

포인터를 저장하자(포인터 변수)

  • 포인터의값 자체는 정수 값이지만 가리키는 자료형에 대한 정보를 가지고 있으므로 정수형 변수에 저장할 수 없다
// 포인터 = 주소 + 자료형 정보
int a;      // 정수 변수
int ap;     // 정수형 변수
ap = &a;    // ❌ 오류: 주소값(int*)을 정수(int)에 저장하려 함
  • 포인터는 포인터가 가진 정보를 그대로 보존하도록 "포인터 변수에 저장해야 한다."

  • 포인터를 저장한 포인터 변수도 참조연산자로 그 것이 가리키는 기억공간 또는 그 기억공간의 값을 사용할 수 있다.

int a;
int *ap = &a;  // 포인터변수의 선언과 동시에 초기와, ap는 변수 a를 가리킨다
*ap = 10;      // 포인터 변수가 가리키는 기억공간에 10을 저장
  • 포인터 변수도 하나의 변수 이므로 주소연산자로 메모리에서의 위치를 구할 수 있다.
int a;
int *ap = &a;
printf("%u\n", ap);   // 변수 a의 시작주소값 52 출력 
printf("%u\n", &ap);  // 포인터 변수 ap의 시작주소값 48 출력

포인터 정리

int a= 10;
int *ap = &a;

printf("%d", a);    // 10
printf("%d", *ap);  // 10
printf("%u", &a);   // 52
printf("%u", ap);   // 52
printf("%u", &ap);  // 48

연습

포인터를 사용한 두 변수의 값을 바꾸기
double a = 1.3;
double b = 1.7;
두 변수 a와b를 가르키는 포인터 변수를 사용하여 값을 바꾸는 프로그램을 작성하세요

#include <stdio.h>

int main(){
    double a = 1.3;
    double b = 1.7;

    double *ap;
    double *bp;
    double temp;

    ap = &a;
    bp = &b;

    temp = *ap;
    *ap = *bp;
    *bp = temp;

    printf("%.1lf, %.1lf\n", a, b);

    return 0;
}

포인터의 필요성

  • 함수들은 독립된 기억공간을 가지므로 다른 함수에 선언된 변수를 사용할 수 없다.

    함수의 한계를 극복

  • 함수는 전달인자가 많아도 리턴되는 값은 오직 하나
  • 따라서 메인함수에 있는 두 변수의 값을 바꾸는 함수는 포인터를 사용해야 한다.
#include <stdio.h>

void exchange(int *, int *);

int main(){
    int a = 10, b = 20;
    exchange(&a, &b);
    return 0;
}

void exchange(int *ap, int *bp){
    int temp;
    temp = *ap;
    *ap = *bp;
    *bp = temp;
}

연습

세 변수의 값을 정렬하는 프로그램
세 개를 입력 받은 후에 내림차순으로 출력하는 프로그램
단 main이 다음과 같이 작성되었을 때 line_up 함수를 정의 필요하면 exchange 함수도 작성

int min(){
	double max, mid, min;
    
    scanf("%lf%lf%lf", &max, &mid, &min);
    
    line_up(&max, &mid, &min);
    printf("%lf, %lf, %lf\n", max,mid,min);
    return 0;
}
#include <stdio.h>

void exchange(double *, double *);
void line_up(double *, double *, double *); 

int main(){
	double max, mid, min;
    
    scanf("%lf%lf%lf", &max, &mid, &min);
    
    line_up(&max, &mid, &min);
    printf("%.1lf, %.1lf, %.1lf\n", max, mid, min);
    return 0;
}

void line_up(double *mp, double *ip, double *np){
    if(*mp < *ip) exchange(mp, ip);
    if(*mp < *np) exchange(mp, np);
    if(*ip < *np) exchange(ip, np);
};

void exchange(double *ap, double *bp){
    double temp;
    temp = *ap;
    *ap = *bp;
    *bp = temp;
}

포인터에 관한 중요한 질문

  • 포인터와 포인터 변수의 크기는 몇바이트인가?

  • 포인터와 포인터 변수의 크기는 가리키는 자료형과는 관계없이 항상 같다(64bit에서는 8Byte)

  • 포인터와 포인터 변수는 자동 형변환이 가능한가?

    • 기본 자료형은 자동형변환이 가능하나 포인터(변수)는 불가능
int *ip;
double db=6.5;
ip = &db;    // 에러!
  • 자동 형변환이 가능하면 정수값이 저장된 기억공간에서 실수값을 참조하는 오류를 범하게 됨
  • 포인터의 형변환 규칙은 함수의 전달인자와 매개변수 사이에도 적용

0개의 댓글