프로그래밍 언어/[ C ]

[ C ] 03. 포인터와 역참조 연산자

kim.svadoz 2020. 8. 13. 10:02
반응형

[ 포인터와 역참조 연산자 ]


포인터 변수에는 메모리 주소가 저장되어 있다. 이 때 메모리 주소가 있는 곳으로 이동해서 값을 가져오고 싶다면 역참조 연산자 *를 이용한다.

#include <stdio.h>

int main(){
    int *numPtr;        // 포인터 변수 선언
    int num1 = 10;        // 정수형 변수를 선언하고 10 저장

    numPtr = &num1;        // num1의 메모리 주소를 포인터 변수에 저장
    printf("%d\n", *numPtr);    // 10 // 역참조 연산자로 num1의 메모리 주소에 접근하여 값을 가져온다
    return 0;
}
# 실행 결과
10
  • 역참조 연산자 *는 포인터 앞에 붙인다. 다음과 같이 numPtr 앞에 *를 붙이면 numPtr에 저장된 메모리 주소로 가서 값을 가져온다. 여기서는 numPtr이 num1의 메모리 주소를 저장하고 있으므로 num1의 값인 10이 출력된다.
  • 즉, 포인터는 변수의 주소만 가리키며 역참조는 주소에 접근하여 값을 가져온다.

image-20200731141038249

// 참고 
// 포인터 선언과 역참조 ??
포인터를 선언할 때도 *를 사용하고 역참조를 할 때도 *를 사용한다. 같은 *기호를 사용해서 헷갈리기 쉽지만 선언과 사용을 구분해서 생각하면 된다.
즉, 포인터를 선언할 때 *는 "이 변수가 포인터다" 라고 알려주는 역할이고, 포인터에 사용할 때 *는 "포인터의 메모리 주소를 역참조하겠다"라는 뜻이다.

int *numPtr;                // 포인터. 포인터를 선언할 때 *
printf("%d\n", *numPtr);    // 역참조. 포인터에 사용할 때 *

이번에는 포인터 변수에 역참조 연산자를 사용한 뒤 값을 저장(할당)해보겠다.

*포인터 = 값;

#include <stdio.h>

int main(){
    int *numPtr;            // 포인터 변수 선언
    int num1 = 10;            // 정수형 변수를 선언하고 10 저장

    numPtr = &num1;            // num1의 메모리 주소를 포인터 변수에 저장

    *numPtr = 20;            // 역참조 연산자로 메모리 주소에 접근하여 20을 저장***********************

    printf("%d\n", *numPtr);    // 20 // 역참조 연산자로 메모리 주소에 접근하여 값을 가져옴
    printf("%d\n", num1);        // 20 // 실제 num1의 값도 바뀐다.
}
# 실행 결과
20
20
  • 역참조 연산자는 값을 가져올 수 도 있고 값을 저장할 수도 있다. 여기서는 *numPtr = 20; 과 같이 numPtr에 저장된 메모리 주소에 접근하여 20을 저장했다. 따라서 printf로 *numPtr을 출력해보면 20이 나온다.
  • 또 한가지 중요한 점은 *numPtr = 20;으로 20을 저장한뒤 printf로 변수 num1의 값을 출력해보면 20이 나온다는 것이다. 왜냐하면 numPtr에는 num1의 메모리 주소가 저장되어 있으므로 역참조 연산자로 값을 저장하면 결국 num1에 저장하게 되는것이다.

image-20200731141740909

  • 역참조 연산자는 자료형을 바꾸는 효과를 낸다. 즉, int *numPtr;에서 *numPtr처럼 역참조하면 pointer to int에서 pointer to를 제거하여 그냥 int로 만든다.
    (int 포인터 -> int)
  • 만약 포인터 numPtr에 변수 num1을 할당한다면 역참조 연산자로 자료형을 맞춰주면 된다.
int *numPtr;
int num1 = 10;

numPtr = num1;            // 컴파일경고, numPtr은 int포인터형이고 num1은 int형이라 자료형이 일치하지 않는다.

*numPtr = num1;            // *numPtr은 int형이고 num1도 int형이라 자료형이 일치한다.
  • 물론 주소 연산자 &도 자료형을 맞춰주는 역할을 한다. ( &을 붙이지 않으면 경고 발생 )
int *numPtr;
int num1;

numPtr = &num1;            // numPtr은 int포인터형이고, &num1은 int형 변수의 주소형이므로 자료형이 일치함
                        // numPtr은 pointer to int, &num1은 address of int이므로 자료형이 일치하는 것!

즉, pointer to int와 address of int는 자료형이 같은것이다.

image-20200731142146129

변수, 주소 연산자, 역참조 연산자, 포인터의 차이 ?!

image-20200731142237234

  • 먼저 변수는 메모리 주소를 몰라도 값을 가져오거나 저장할 수 있다. 그냥 변수에 값을 할당하거나 그대로 출력하면 된다.
  • 주소 연산자 &는 변수의 메모리 주소를 구한다. 이 그림에서 10을 감싸고 있는 상자는 메모리 공간을 뜻하는데 주소 연산자는 메모리 공간이 어디에 있는지 위치만 알아낼 수 있다.
  • 역참조 연산자 *는 그림에서 보면 상자안까지 들어가서 값을 가져오거나 저장한다. 즉, 메모리주소를 알고 있으므로 메모리 주소를 거쳐서 그 안에 있는 값을 가져오거나 저장한다.
  • 마지막으로 포인터는 변수의 메모리 주소만 가리킨다. 따라소 포인터는 메모리 공간이 어디에 있는지 위치만 알고 있다.
반응형