본문 바로가기

언어/C

포인터의 이해(1) - *, & 연산자의 의미

C언어를 공부하게 되면서 C언어의 꽃인 포인터를 정리해보았다.

먼저, 포인터를 정리하기 전에 메모리의 주소에 대해서 이해해보자.

 

 

메모리 주소

데이터들은 특정 메모리 공간에 저장되어 있는데 공간 하나당 보통 1 바이트이다.

예를 들어, int형 변수를 정의하면 4바이트의 크기를 가지고 있어 4칸을 차지하게 된다.

 

int a = 1234;

 

 

 

 

 

 

 

 

 

 

 

이처럼 int 변수 a를 정의하면 해당 데이터가 저장되는 방의 주소(0x134232)가 붙여진다.

이 주소를 통해서 데이터를 가져오게 된다.

다시 말해서, 변수는 운영체제로부터 자신의 크기만큼 각 메모리를 할당 받는다. 그리고 그 영역에 값을 저장하여 사용한다. 그리고 각 메모리는 바이트 단위마다 주소를 가지고 있고, 그 주소를 통하여 해당 변수의 값을 가져올 수 있다.

 

 

포인터란?

포인터는 메모리 상에 위치한 특정한 데이터의 시작 주소값을 보관하는 변수이다.

 

이제 본론인 포인터에 대해서 알아보자.

먼저, C언어에서 포인터를 정의하는 방법은 2가지이다.

  • (포인터에 저장된 주소값과 관련된 데이터 자료형) *(포인터 이름);
  • (포인터에 저장된 주소값과 관련된 데이터 자료형)* (포인터 이름);

이처럼 포인터에도 자료형을 정의해주고 포인터 변수명을 정의하면 됩니다.

 

int* p;

 

 

int형 데이터의 시작 주소값을 저장하는 변수는 p인 것이다.

즉, 포인터도 int, char 변수들과 다르지 않게 특정한 데이터를 보관하는 하나의 '변수'인 것이다.

이때 특정한 데이터는 주소값을 의미하는 것이고, 특정 데이터의 시작 주소값을 보관하는 변수로 생각하면 된다. 

 

 

& 연산자

 

그렇다면 우리는 어떻게 특정 변수의 주소값을 알 수 있을까?

바로 & 연산자를 사용하여 알 수 있다.

 

사용 방법은 해당 변수 앞에 &를 붙여주면 된다.

 

& /*주소값을 계산할 데이터*/

 

 

간단한 예를 들어서 주소값을 확인해보자.

 

#include <stdio.h>

int main() {
	int a;
    a = 123;
    
    printf("a의 주소 : %p \n", &a);
    return 0;
}

 

 

결과 값은 컴퓨터에 따라 다르게 나올 수 있다. 또한, 실행할 때마다 다른 결과가 나오는 것을 알 수 있다.

 

 

* 연산자

지금까지 배운 것을 정리하면, 포인터는 주소값을 보관하는 데이터 타입에 *를 붙여서 정의하고 특정한 데이터의 주소값을 저장한다. 저장된 주소값은 & 연산자를 통하여 알 수 있다.

 

그렇다면 해당 주소값에 대응되는 데이터를 가져오는 연산자에 대해서 알아보자.

이 연산자는 * 이다. 이 연산자의 역할을 쉽게 생각하면 저장된 주소값에 위치한 데이터라고 생각하면 된다.

 

예를 들어서 알아보자

 

#include <stdio.h>

int main() {
    int a;
    int* p;

    p = &a;
    *p = 123;

    printf("a의 주소 : %p \n", &a);
    printf("p : %p \n", p);
    printf("*p : %d \n", *p);
    printf("a : %d \n", a);
    return 0;
}

 

 

먼저, 변수 a와 포인터 변수 p를 정의하고, 포인터 변수 p에 a의 주소값을 넣었다.

*p = 123; 은 포인터 변수 p에 저장된 주소에 데이터 123을 넣으라는 의미이므로 다음과 같은 결과가 나온 것이다.

 

 

 

마지막으로 정리하자면 연산자 * 는 포인터가 저장한 주소값이 가리키는 변수의 값을 가져오는데 사용하고, & 연산자는 변수의 주소값을 불러온다.

그리고 포인터 또한 변수이기 때문에 포인터도 주소값을 가진다.

이와 관련된 내용은 이중포인터를 공부할 때 더 자세하게 알아보겠다.