POST

C언어 포인터(Pointer)란? 포인터의 완벽 이해

"포인터란 어떠한 값을 저장하는게 아닌 어떠한 값의 주소(Address)를 저장하는 것 이다!"


어떠한 값의 주소라함은 해당값이 저장된 컴퓨터 메모리상의 주소를 의미한다.

ex) num이라는 변수에는 5의 값이 저장되어있다. 그리고 *pnum이라는 포인터 변수에는 num의 주소 123456이 저장 된다는 것이다.


포인터 변수를 만들때는 변수이름앞에 *을 붙여주면 그변수는 포인터 변수가 된다.

(사용할때 일반변수와의 구분을 위해 주로 '*p변수이름'의 형식으로 사용한다.)


간단하게 포인터 함수를 이용하여 포인터 변수 정의와 &연산자에 대하여 설명을 하겠다.

#include<stdio.h>


int main(void)

{

int *pnum; // 포인터 변수 선언

int num = 12345; // 일반변수 선언 & 초기화

pnum = &num; // num의 주소값을 반환하여 pnum에 저장

printf("num의 값: %d\n", num);

printf("num변수의 주소:%p\n", &num);

printf("pnum변수의 값 :%p\n", pnum);

printf("pnum이 가리키는 값: %d\n", *pnum);

}

실행결과는 아래와 같다.



이것의 결과를 보면 pnum의 실질적인 값은 num의 주소이며 num의 값을 가리킨다는 것을 알수있다.


여기서 &연산자는 &오른쪽에 오는 피연산자의 주소값을 반환하는 연산자이다.


그리고 포인터도 가리키고자 하는 변수의 자료형에 따라 포인터변수도 그에 맞춰 다르게 선언한다 - 자료형 보러가기

ex) double num;

double *pnum; // double형 포인터 변수 pnum


char cha;

char *pcha; // char형 포인터 변수pcha

이런식으로 가리키고자하는 변수와 맞추어 준다.


사실 주소값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띤다. 하지만 모두다 똑같이 int형으로 포인터 변수를 선언한다면 다른 사용자나 자신 그리고 시스템은 해당 포인터 변수가 무엇을 가리키는건지 알기 힘들것이다. 

우리는 위와같이 *이붙은 자료형은 포인터 형이라한다. 물론 포인터도 값을 저장하는 변수이기에 자료형의 범주에 포함 된다.


또하나의 사실은 *의 위치는 크게 상관이 없다.

ex) int* pnum;

int *pnum;

int * pnum;

위처럼 프로그래머 마음대로 골라 쓰면된다.


*연산자는 포인터가 가리키는 메모리 공간에 접근할때 사용되는 연산자이며 포인터 변수를 이용해 포인터 변수가 가리키는 변수의 값을 바꿀 수도잇다. 아래의 코드를 살펴보자.

#include<stdio.h>


int main(void)

{

int *pnum; // 포인터 변수 pnum 선언

int num = 12345; // num값 초기화

pnum = &num; // pnum에 num의 주소값을 저장

printf("변경전 num의 값 : %d\n", num);

printf("변경전 pnum의 값 : %d\n", *pnum);

*pnum = 54321; // pnum이 가리키는 변수의 값 변경

printf("변경후 num의 값 : %d\n", num);

printf("변경후 pnum의 값 : %d\n", *pnum);


}




널 포인터(NULL Pointer)

포인터의 초기값은 무엇으로 주어야할까?

포인터를 선언만하고 초기화해주지않으면 내부에는 쓰레기 값으로 채워지는데 이는 그 포인터 변수가 어디를 가리킬지 아무도 알수없다.

설령 포인터가 가리키는 주소가 메모리상에서 아주 중요한공간이라도 모를것이다.

거기다가 아래의 코드처럼 *연산으로 임의의 수를 저장하면 프로그램에 치명적인 결과를 가지고 올수있다.

 int main(void)

{

int *pnum;

*pnum=200;

}


그렇다면 초기값을 대충 1234로해야하나?

이것도 안된다. 왜냐하면 이 1234번지가 메모리의 어디에 있는지 알수없다. 고로 쓰레기 값으로 채우는 것과 다를바없다.

그럼 방법이 없지않은가? 라고 할 수 있다. 하지만 방법은 있다.

바로 NULL값을 이용하는것이다.

아래의 코드를 보자

int main(void)

{

int *pnum1 = 0;

int *pnum2 = NULL;

}

이둘이 의미하는바는 같다 왜 0과 NULL이 같은 의미를 지니냐면 0은 아스키코드에서 NULL이기 때문이다. - 아스키코드표 보기

그리고 0이 라는 숫자가 들어가면 *pnum1이 0번지를 가리키진않는다.

여기서 0(NULL)의 의미는 해당 포인터 변수는 아무것도 가리키고 있지 않다고 할수있다.

.

.

.

C언어를 배우며 처음에는 포인터에 대해서 이해하기 힘들것이다 하지만 계속해서 사용을 하고 오류를 수정하다보면 점차 포인터의 사용법과 쓰임새를 알수 있을 것이다.


자, 이제 아래의 문구를 다시 읽었을때 어느정도 이해가 되었는가?


"포인터란 어떠한 값을 저장하는게 아닌 어떠한 값의 주소(Address)를 저장하는 것 이다!"