Language/C

C_Char09.포인터(개념)

1. 포인터의 기본 개념

변수 = 메모리 공간 / 변수명 = 공간 식별 이름

단, 서로 다른 함수(블럭)에 존재하면 전혀 다른 변수로 사용이 된다.

이러한 경우에도 데이터를 공유할 수 있게 하기 위해 포인터 를 사용한다.

  • 메모리의 주소

메모리 = 데이터를 넣고 꺼내는 공간으로 찬장과 같다고 하자.

우리는 이 찬장의 위치를 알아야지 찬장에 있는 물건(데이터)를 꺼낼 수 있다.

프로그램에서는 사용하는 메모리의 위치를 주소 값으로 식별할 수 있다.

이러한 주소값은 byte(바이트) 단위로 구분 된다.

 

메모리 ( 주소 1개당 1byte 할당 )

 

2. 주소 연산자 &

주소 = 변수가 할당된 메모리 공간의 시작 주소

주소 연산자 & 를 사용해서 구현하며, 원하는 위치부터 변수의 크기만큼 메모리 사용이 가능하다.

#include <stdio.h>

int main(void)
{
    //변수  선언문 실행 
    int a;        // int형 변수선언
    double b;    // double형 변수 선언
    char c;        // Char형 변수 선언

    printf("int형 변수의 주소 : %u\n", &a);    [^1]:주소 연산자로 주소 계산
    printf("double형 변수의 주소 : %u\n", &b);
    printf("char형 변수의 주소 : %u\n", &c);

    return 0;

}
>>    int형 변수의 주소 : 15727976
    double형 변수의 주소 : 15727960
    char형 변수의 주소 : 15727951

변수 선언문이 실행되면, 각 자료형의 크기만큼 메모리에 저장 공간이 할당된다.

이때, 주소연산자& 를 사용하면 변수가 할당된 메모리 공간의 시작 주소 값을 알 수 있다.

&변수명

변수에 할당된 메모리의 시작 주소를 확인하고,

시작 주소에 변수의 크기를 더하면 변수의 메모리의 할당 범위를 알 수 있다.

 

3. 간접참조연산자 ( * )

앞에서는 단지 메모리의 주소를 출력하는 법을 알아보았다.

하지만, 필요할 때마다 계속 주소 연산을 수행하는 것은 불편하기에 한 번 구한 주소를 저장해서 사용하는법을 알아보자.

포인터

변수의 메모리 주소를 저장하는 변수로 일반 변수와 마찬가지로 선언 후 사용한다.

다만, 선언할 때 변수 앞에 * 만 붙여주면된다.

#include <stdio.h>

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

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

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

    return 0;
}
>>    포인터로 a값 출력 : 10
    변수명으로 a값 출력 : 10

 

자료형 *변수명;

포인터 이름을 짓고, 변수명 앞에 *를 붙인다.

여기서 *는 포인터임을 표시하는 기호이다.

포인터의 자료형은 변수의 자료형을 적어준다.

여기서, 포인터 자료형은 저장할 주소가 어떤 변수의 주소인지 그 변수의 자료형을 적는다.

int *pa;

포인터 변수가 할당되면, 일반 변수와 마찬가지로 메모리 저장공간이 할당되고, 이후에는 변수명으로 사용할 수 있다.

pa = &a;    //포인터에 a의 주소 대입

pa ← a 포인터 pa는 변수 a를 가리킨다.

즉, *pa로 변수 a를 사용할 수 있다. ( *pa == a)

*pa = 10
printf("a의 값은 : %d", a);
>> a의 값은 : 10

이렇게 배운 포인터를 이용한 사용법을 알아보자.

  • 포인터를 사용한 두 정수의 합과 평균
#include <stdio.h> 

int main(void)
{
    int a = 10, b = 15, total;    //변수 선언과 초기화
    double avg;        // 평균을 저장할 변수
    int *pa, *pb;    // 포인터 동시 선언

    int *pt = &total;     // 포인터 선언과 초기화
    double *pg = &avg;    // double형 포인터 선언과 초기화

    pa = &a;    //포인터 pa에 변수 a의 주소 대입
    pb = &b;    //포인터 pb에 변수 b의 주소 대입

    *pt = *pa + *pb;    // total = a + b 와 같음 
    *pg = *pt / 2.0;    // avg = total / 2.0 

    printf("두 정수의 값 : %d, %d\n", *pa, *pb);
    printf("두 정수의 합 : %d\n", *pt);
    printf("두 정수의 평균 :%.1lf\n", *pg);

    return 0;

}
>>    두 정수의 값 : 10, 15
    두 정수의 합 : 25
    두 정수의 평균 :12.5

 

4. const를 사용한 포인터

const = 가리키는 변수의 값을 바꿀 수 없다.

라는 의미로, 이렇게되면 변수이 사용하는 것과는 다른 의미를 가진다.

#include <stdio.h> 

int main(void)
{
    int a = 10, b = 20;
    const int *pa = &a;        //*pa는 변수 a를 가리킨다

    printf("변수 a값 : %d\n", *pa);    // 포인터를 간접 참조하여 a 출력
    pa = &b;        // 포인터가 변수 b를 가리키게 된다.

    printf("변수 b값 : %d\n", *pa);    //포인터를 간접 참조하여 b 출력
    pa = &a;        // 포인터가 다시 변수 a를 가리킨다
    a = 20;            // a를 직접 참조하여 값을 바꾼다.

        printf("변수 a값 : %d\n", *pa);
    // 포인터로 간접 참조하여 바뀐 값 출력

    return 0;
}
>>    변수 a값 : 10
    변수 b값 : 20
    변수 a값 : 20

const int *pa = &a; 에서 *pa를 선언할 때 const로 상수화 하였다.

만약, const가 일반 변수처럼 포인터 값을 고정시킨다면, pa = &b; 에서 pa는 다른 변수의 주소를 저장 할 수 없다.

하지만 출력 결과에서 pa는 const의 사용과 무관하게 변수 b의 주소를 저장하고, 간접 참조해 출력하고 있다.

왜 이런걸까?

const int *pa = &a; 여기서 사용된 const의 의미는

*pa가 가리키는 변수 a는 pa를 간접 참조해서 바꿀수 없다.

그렇기에, *pa = 20; 처럼 pa의 값을 통해 a를 바꾸려고 하면 에러가 발생한다.

 

  • 응용 문제 ( 한번 생각해보고 실행해보자)
#include <stdio.h> 

int main(void)
{
    int a = 10, b = 20;
    const int *pa = &a; // 포인터가 가리키는 곳의 데이터를 상수화 ( 주소변경 O)
    int* const pb = &b; // 포인터 자체가 상수화 ( 주소변경 X )

    printf("변수 a값 : %d\n", *pa);
    pa = &b;
    b = 50;

    printf("변수 b값 : %d\n", *pa);
    pa = &a;
    a = 20;

    printf("변수 a값 : %d\n", *pa);
    printf("변수 b값 : %d\n", *pb);

    return 0;
}
>>    변수 a값 : 10
    변수 b값 : 50
    변수 a값 : 20
    변수 b값 : 50

[ 중간 정리 ]

  1. 포인터는 메모리를 사용하는 또 다른 방법이다.
  2. 주소 연산자 & 로 변수가 할당된 메모리의 위치를 확인한다.
  3. 포인터로 가리키는 변수를 사용할 때 *간접 참조 연산자 * * 를 사용한다.
  • 주소 연산자 ( 변수가 할당된 메모리의 시작 주소 값 구함)

int a; & a

  • 포인터 ( 시작 주소 값을 저장하는 변수, 가리키는 자료형을 표시하여 선언한다. )

char *pc; int *pa double *pd

  • 간접 참조 연산자 ( 포인터에 사용, 포인터가 가리키는 변수를 사용 )

*pi = 10;


 

'Language > C' 카테고리의 다른 글

C_Char13-1. 변수 사용 영역  (0) 2021.05.10
C_Char09.포인터(이해)  (0) 2021.05.09
C_Char08.배열  (0) 2021.05.09
C_Char07.함수  (0) 2021.05.09