본문 바로가기
C언어/포인터

[C언어] 포인터에 대해 이해하기(포인터 - 1)

by 프링글's 2022. 7. 3.

 

Ⅰ.포인터를 이해하기 앞서

 

우리가 저장하는 모든 데이터는 메모리 상의 공간에 저장되게 된다. 예를 들어 int형 변수를 만들어 값을 저장하면 4바이트짜리 공간에 4바이트짜리 데이터를 저장하는 식으로 처리된다. 이러한 공간들을 구분하기 위해 컴퓨터 내에서 메모리 상의 공간마다 주소가 붙어있게 된다.

포인터는 이러한 주소값들을 저장하기 위해 만들어진 변수이다. 결국 포인터라는게 int, char, float와 같은 자료형들과 다른게 아닌 '변수'라는 점을 기억하자. 특별히 데이터의 주소값을 저장하는 변수.

그래서 int형 변수 a에 2를 저장했다가 이후에 3을 저장하는게 가능하듯이 포인터도 a라는 변수를 가리켰다가 b라는 변수를 가리켰다가 하며 바뀔 수 있다.

int a;
a=2;
a=3;		//a값이 2에서 3으로 바뀜

int b;

int *p;
p = &a;
p = &b;		//p가 a를 가리켰다가 b를 가리킴

 

 


Ⅱ.포인터에 대해 알아보자

우선 위에서도 말했듯 포인터는 데이터의 주소값을 저장하는 변수이다.

그렇다면 포인터가 데이터의 주소를 처음부터 끝까지 저장하고 있을까? 물론 그건 아니다. 특별히 포인터는 메모리 상에 위치한 특정 데이터의 시작주소값을 보관하고있다.

즉, 위에서 말한 포인터의 정의를 수정하자면 포인터메모리 상에 위치한 특정한 데이터의 시작주소값을 보관하는 변수라고 정의할 수 있겠다.

 

우리가 변수를 정의할 때 int, char, float와 같은 형(type)이 있었던 것처럼 포인터도 이러한 형을 가지고 있다. 다시말해서, 메모리상의 int형 데이터의 주소값을 저장하는 포인터와 char형 데이터의 주소값을 저장하는 포인터는 서로 다른 포인터라고 볼 수 있다. 그래서 C언어에서 포인터를 정의하는 방법은 다음과 같다.

(포인터가 가리킬 데이터의 형) *(포인터의 이름)

(여기서 *의 위치는 형(type)의 바로 뒤에 있어도 같은 의미이다. int* p; 나 int *p;나 똑같다는 말)

 

그런데 왜 포인터에 형(type)이 필요할까? 어차피 주소값은 모두 8바이트(64비트 컴퓨터 기준)이고 그냥 pointer라는 형을 만들면 더 편하지 않았을까?

그 이유는 바로 위에서 내린 포인터의 정의에서 찾을 수 있다. 우리는 포인터가 데이터의 시작주소를 저장한다고 정의를 내린 바 있다. 그런데 우리가 포인터가 가리키는 주소에 있는 데이터를 읽어들이고 싶은데 형(type)이 없다면 몇바이트까지가 읽어들여야하는 값인지 알 방법이 없다. 이런 이유로 포인터에 형을 붙여줌으로써 "이 포인터가 이런 형태의 데이터를 가리키고 있어요~"하고 알려주는 것이다.

 

 


Ⅲ.&연산자

그럼 우리가 포인터에 주소값을 대입하기 위해선 주소값을 알아낼 수 있어야 한다. 이때 사용하는 연산자가 &연산자이다.

&연산자를 사용하고 싶을 때는 다음과 같이 하면 된다.

&(주소값을 계산할 데이터)

&를 and연산자라고 생각한다면 그것도 당연히 맞다. 그저 주소값 연산자로 쓰일때와 항의 개수가 다를 뿐이다. and연산을 할 때는 a&b와 같이 앞뒤로 항 두개가 붙었다면 주소값 연산자로 쓰일때는 &a와 같이 단항연산자로 쓰인다.

 

그럼 &연산자를 이용해 포인터에 주소값을 저장해보자.

#include <stdio.h>
int main(){
    int *p;
    int a;
    p = &a;
    
    printf("%p\n", p);
    printf("%p", &a);
    
    return 0;
}

이를 실행하면 다음과 같은 결과가 나온다.

000000000062FE14
000000000062FE14

다음과 같이 a의 주소값이 포인터 p에 잘 저장된 것을 확인할 수 있다.

물론 주소값은 임의로 저장되기 때문에 결과값은 실행할 때마다 무작위로 바뀐다.

 


Ⅳ.*연산자

&연산자로 데이터의 주소값을 불러올 순 있는데, 거꾸로 주소값에 대응되는 데이터를 가져올 수는 없을까? 그럴때 사용하는 연산자가 바로 *연산자이다.

*연산자는 다음과 같이 사용할 수 있다.

#include <stdio.h>
int main(){
    int *p;
    int a;
    
    p = &a;
    *p = 2;
    
    printf("%d\n", a);
    printf("%d", *p);
    
    return 0;
}

이 코드의 결과값은 다음과 같이 나온다.

2
2

즉, p가 a를 가리키는 포인터이므로 *p는 a라는 데이터를 가져오게 되므로 *p는 a와 동일하다고 보아도 무방하다. 그래서 *p에 2를 대입했더니 a에도 2가 대입되었고, a를 출력해도 2, *p를 출력해도 2가 출력된 것이다.

 

 

(위 포스트는 https://modoocode.com/23를 참고하여 제가 이해한대로 작성하였습니다. 틀린 내용은 지적바랍니다.)

 

씹어먹는 C 언어 - <12 - 1. 포인터는 영희이다! (포인터)>

 

modoocode.com

 

댓글