포인터란 무엇인가?
변수가 선언되고, 값이 할당되면 메모리 공간에 저장되는데,
메모리 공간의 위치인 주소값을 통해 접근을 할 수 있다.
주소값을 저장하기 위한 변수가 포인터 변수이다.
' * '
1.포인터 변수의 데이터 타입을 참고해서 (누구를?)
2.포인터가 가리키는 주소값에 접근 (어디에?)
" & "
변수의 주소값을 반환
int main()
{
int num1 = 100; // int형 변수 num1에 값 할당
int *pnum = &num ; // 포인터 pnum은 num의 주소값을 통해 메모리 공간에 접근
printf("&d\n", *pnum); // pnum이 가리키는 메모리 공간에 저장된 값 출력
return 0;
}
100
주소값은 정수일 뿐이다. 그렇다면 Int type 변수에 저장할 수 있는데 굳이 왜 pointer 에 따로 주소값을 저장할까?
질문대로 pointer 변수 대신 int type 변수에 주소값을 저장해보자.
int main()
{
int num = 20; // 변수 num에 값 20 할당
int ptr = # // 정수형 ptr 변수에 num의 주소값 할당.
*ptr = 30; // Error !
return 0 ;
}
ptr 변수가 가리키는 것은 num이 가지고 있는 첫번째 값의 주소값인데,
이 값을 int type(4byte), double type으로 읽어야 하는지에 대한
정보는 담겨 있지않다. 즉, ptr변수는 자신이 가리키는 주소값을 어떻게 읽어야 할 지 모른다.
정수형 변수ptr은 주소값은 가지고 있지만, 주소값에 담겨있는 메모리 공간에 대한 정보를 알 수 없기 때문이다.
pointer 변수도 자료형이 구분 되는데, 왜 그러한가?
주소값에 담겨 있는 메모리 공간에 대한 정보가 바로 포인터의 자료형이기 때문이다.
예를 들어, 다음의 소스를 컴파일러에 넘기면 에러가 발생한다.
int main()
{
int ptr ;
*ptr = 17 ; // * 는 17을 어떤 데이터 형태로 읽어야하는지 모름
return 0;
}
주소값에 접근하기 위해서 컴파일러에는 두 가지 정보를 주어야하기 때문이다.
주소값(&)을 통해 메모리 공간에 접근(*)한다는 것을 이해하자.
그렇다면 다음과 같이 수정할 수 있겠다.
int* ptr = 17; // ptr이 가리키는 메모리 공간에 접근해서, 17을 저장하라.
메모리 공간의 주소값의 데이터 형태도 중요하지만, 주소값 설정시 그 주소값이 어떤 메모리를 가리키는 지 생각해보는 것도 매우 중요하다.
포인터의 주소값이 쓰레기 값인 경우ㅡ
int main(void)
{
int* ptr; //ptr이 쓰레기 값으로 초기화, 어떤 메모리를 수정할 지 모르는 위험한 코드
*ptr = 200 ; // 200이 어떤 메모리공간을 가리키는 지 알수 없음
}
모르는 메모리 공간에 접근한 경우,
int main(void)
{
int* ptr = 125; // 주소값 125번지는 어디인가? 모름
*ptr =10 ; // 125번지 값을 10으로 바꾸는 것은 위험
}
NULL 포인터 (안전한 경우)
int main()
{
int* ptr = 0 ; // ptr 주소값 0 으로 설정
int* ptr2 = NULL; // NULL == 0 이므로 동일
}
***
0은 0번지로 해석되는 것이 아니라, 아무 값도 가지지 않는다는 의미로 해석된다.