포인터에 대한 기본적인 지식

     




많은 분이 C언어를 배울 때 가장 어려워하는 부분이 포인터입니다. 학부생 1학년들에게 C언어 실습과목을 맡은 적이 있는데, 학기가 끝날 때까지 포인터를 완벽하게 이해한 학생은 별로 없더군요. 사실 포인터는 이론적으로는 쉽게 정의가 가능합니다. 


“포인터는 주소값을 갖는 변수형이다.” 


왜 이 정의가 어려운지 생각해봤습니다. 저도 1학년 때 C언어를 처음 배우면서 포인터를 상당히 어려워했는데, 고학년이 되어서 다시 보니 상당히 쉬운 정의였습니다. 아마 고학년 때 배우는 컴퓨터 구조에 대한 지식이 있고 없고가 상당히 중요해 보입니다. 컴퓨터가 자료를 어떻게 저장하는지에 대해 모르는 1학년들 입장에서는 “주소값이 뭐지?”라는 의문을 갖게 됩니다. 따라서 먼저 컴퓨터가 자료를 어떻게 메모리에 저장하는지에 대한 기본적인 개념을 알아야 포인터를 쉽게 배울 수 있습니다.


C에서 자료를 선언하면 컴퓨터는 메모리에 선언한 자료를 저장할 공간을 만들게 됩니다. 정수형 자료를 하나 선언하면 메모리에 4Byte의 공간을 할당하고, 그 자리에 정수형을 저장할 수 있도록 합니다. 


int number = 4;


즉 number라는 정수형 변수를 저장하기 위해 메모리에 4byte의 공간을 만들고, 정수값 ‘4’를 저장하게 되죠. 우리는 number라는 변수명을 이용해 정수값 ‘4’를 사용할 수 있지만, 컴퓨터는 number가 ‘4’라는 것을 인식하지 못합니다. 대신 컴퓨터는 number라는 변수가 저장된 메모리의 위치를 알고 있고, 사용자가 number를 호출하면 number가 저장되어있는 메모리에 접근해 저장된 값 ‘4’를 호출하게 되죠. 


따라서 선언된 모든 변수는 메모리에 자기만의 공간을 할당받고 그 안에 값들을 저장하고 있습니다. 

메모리에 저장된 값에 접근하기 위해서는 실제로 저장되어있는 공간의 주소값을 알아야 합니다.





&number에서  &연산자는 주소를 뜻합니다. 따라서 &number는 number가 저장된 주소를 나타냅니다. 메모리는 보통 한 블럭에 1byte를 나타냅니다. number는 0x0000~0x0003까지 4byte를 차지하고 있지만, 주소값을 표현할 때는 가장 앞 byte인 0x0000을 가리킵니다.  


주소값이 0x0000을 저장하기 위해서는 주소를 저장할 수 있는 변수형이 필요한데, 바로 포인터 변수입니다. 사용방법은 변수명 앞에 *연산자를 사용하면 됩니다.


int * pointerInt = &number;


pointerInt는 인트형 변수가 저장된 메모리의 주소값을 저장하는 포인터변수입니다. &연산자를 이용해 number의 주소값이 저장되어 있습니다.






포인터 변수 또한 변수이기 때문에 메모리에 저장됩니다. 여기서는 임의주소인 0x0012에 pointerInt변수가 저장되었습니다. pointerInt에 저장된 값은 0x0000으로 number가 저장된 메모리 주소입니다. 이때 pointerInt를 어떻게 출력하느냐에 따라 값이 다르게 출력됩니다.


pointerInt => 0x0000

*pointerInt =>     4


위에 pointerInt는 pointerInt에 저장된 값이 출력됩니다. 실제로 pointerInt에 저장된 값은 number의 주소인 0x0000이기 때문에 출력 역시  0x0000입니다. 하지만 *pointerInt의 경우 pointerInt에 저장된 주소에 저장된 값을 출력합니다. 즉 *pointerInt는 *(0x0000)이며 실제로 0x0000에 저장된 4의 값을 가리킵니다. *가 있고 없고의 차이점을 이해하셨나요?





그림으로 보면 쉽게 이해할 수 있습니다. pointerInt는 실제 pointerInt에 저장된 값을 출력하고, *pointerInt는 pointerInt에 저장된 값을 주소값으로 갖는 데이터를 출력하게 됩니다. 컴퓨터 구조에서는 이런 형태를 indirect address라고 표현합니다. 직접 주소에 있는 데이터를 출력하지 않고, 주소에 있는 데이터를 주소값으로 갖는 값을 출력하는 간접적인 형태입니다.


반대로 number처럼 실제 number의 주소에 값이 저장돼있는 형태는 direct address라고 표현합니다. 

하지만 굳이 number라는 변수를 이용해 4를 출력할 수 있는데 주소값을 알아야 할 필요가 있을까요? 여러 이유가 있지만, 포인터를 배울 때 가장 많이 사용되는 예제는 Call by Value와 Call by Reference입니다. (이 부분에 대해서는 따로 목록에 있기 때문에 찾아보시면 됩니다.)


또 포인터 변수에 몇가지 특징이 있는데 포인터 변수는 어떤 변수로 선언하든지 4byte의 메모리 공간을 갖습니다. 왜냐하면, 포인터 변수는 메모리의 주소값을 갖기 때문입니다. 메모리의 주소는 보통 4byte로 표현되기 때문에 char*로 선언한 변수와 int*로 선언한 변수 모두 4byte의 저장공간이 할당됩니다. char형 포인터도 저장되는 주소는 4byte로 표시되기 때문입니다. 


포인터의 경우 필기나 면접에서 개념을 묻기보다는, 할당되는 메모리의 크기에 대한 문제로 자주 등장하기 때문에 기억해 두시면 좋겠습니다.











반응형

댓글

Designed by JB FACTORY