포인터란 무엇인가? 파트 1

C 언어를 공부하게 되면 초보자가 가장 어렵게 느끼는 부분중의 하나가 포인터이다. 포인터란 무엇인가, 왜 포인터를 쓰게 되는가를 좀 다른 시각으로 접근해서 써보고자 한다. 먼저 예를 들어보겠다.

자. 오늘 아침 당신은 레임프루프 홈페이지를 보고 있다가, 아주 재미있는 게시물을 읽게 되었다. 당신은 이 게시물을 다른 친구에게도 보여주고 싶다고 생각을 해서, 메일로 이 내용을 보내주기로 했다. 재미있는 게시물을 친구에게 보내주려면 어떻게 해야 할까? 다음과 같이 2 가지 방법을 생각할 수 있다.

방법 1. 게시물을 마우스로 쭉 긁어서 Ctrl+C 로 카피한 후에, 메일 프로그램이 떠 있는 윈도우에다 Ctrl+V 로 붙여넣은 다음에, 내용물을 그대로 편지로 보낸다

방법 2. 게시물의 링크를 적어서 메일로 보내준다.

어떤 방법을 쓰던간에 당신의 친구는 당신이 보내준 게시물을 읽을 수 있을 것이다. 결과적으로는 똑같은 일을 한 셈이지만, 당신이 한 행동은 개념적으로, 전송된 내용 상에서도 매우 다른 일을 한 것이다.

여기에서 다음과 같은 차이점들을 발견할 수 있다.

i) 첫번째 방법은 내용물을 '복사'해서 직접 건네준 것이고,
   두번째 방법은 내용물의 '참조'를 만들어서 보내준 것이다.

ii) 첫번째 방법은 상대가 내용물을 '직접' 억세스 가능하게 만들어서 보내준 것이고, (메일을 열면 내용물이 직접 보인다)
    두번째 방법은 상대가 내용물을 '간접' 억세스 가능하게 만들어서 보내준 것이다 (메일을 연 후에 링크를 다시 클릭해야 보인다)

iii) 첫번째 방법은 원본의 용량만큼 보내준 양이 생성되어 보내지지만,
    두번째 방법은 원본이 아무리 크건 작건, 링크의 크기에 해당하는 몇십바이트만 보내진다

iv) 첫번째 방법은 원본이 바뀌게 되었을 경우 (예를 들면 후에 재미있는 덧글이 더 달렸다던가) 에도 영향받지 않지만,
    두번째 방법은 원본의 수정사항에 관계없이 상대에게 모든 내용을 전달하게 된다

v) 첫번째 방법은 원본이 사라졌을 경우에도 상대방은 내용을 볼 수 있지만,
    두번째 방법은 원본이 사라지게 되면 볼 수 없게 된다.

vi) 첫번째 방법으로 여러사람에게 보낼 경우, 그에 비례해서 용량부담이 계속 커지게 되지만,
     두번째 방법의 경우에는 아무리 여러사람에게 보내도 거의 영향을 받지 않는다

vii) 게시물의 내용이 동영상이나 음악처럼 용량이 큰 경우에는 거의 두번째 방법을 사용하게 된다.

viii) 첫번째 방법의 경우, 게시물에 덧글을 달거나 할 수가 없지만,
      두번째 방법의 경우, 받은 친구도 게시물에 덧글을 달 수가 있다.

여기까지 읽었으면 이해가 갈지 모르겠지만, 두번째 방법에서 사용한 URL 링크라는 것은 사실 포인터의 일종이다. 참고로 URL 은 Universal Resource Locater 의 약자이다. Locater 의 의미는 포인터(Pointer) 와 거의 같다고 생각할 수 있다.

C 언어로 프로그래밍을 하다보면 여러개의 함수들을 만들게 된다. 그리고 각 함수들은 여러가지 복잡한 연산들을 수행하게 되는데, 그 연산의 대상이 되는 변수나 구조체는 작을 수도 있고, 커질 수도 있다.

작을 경우에는 별 관계가 없겠지만, 매우 커질 경우에는 어떻게 해야 할까? 포인터는 그럴때 반드시 사용하게 되는 것이다. vii) 에서 지적한 것은 바로 이러한 경우이다.

포인터의 가장 기본적인 아이디어는 '간접'적인 억세스이다 (indirection). 메일을 받은 상대가, 메일의 내용을 직접 읽는 대신, 메일 안에 써 있는 링크를 한번 더 클릭하는 수고를 함으로써, 포인터의 장점을 살릴 수 있게 되는 것이다. 마찬가지로 어떤 함수에서 데이타를 다른 함수에 포인터로 넘겼을 경우에, 받아온 함수는 데이타를 모두 카피해오는 대신 포인터를 갖고 데이타를 읽거나 고칠 수 있다.

위에 i) 부터 vii) 까지 열거한 중에 포인터의 장점을 꼽는다면 iii), iv), vi), vii), viii) 등의 경우를 들 수 있을 것이다. 물론 많은 부분이 겹치는 얘기이므로, 다시 정리하자면, 용량이 큰 데이타를 다른 사람에게 억세스할 수 있도록 해줄 때, 장점이 발생한다는 얘기이며, 그 결과에도 영향을 줄 수 있다는 의미이다.

그 반면에 포인터의 단점을 들 수 있는 경우는 ii), v), 같은 경우를 들 수 있다. 아무래도 한번 더 링크를 클릭하는 수고를 해야 하니까 더 느려지기 마련이고, 원본이 사라지는 경우에는 링크를 클릭했을 경우 에러가 나게 된다. 컴퓨터 프로그래밍의 경우도 마찬가지다. 직접 데이타를 억세스하는 경우보다는 포인터를 통해서 간접적으로 억세스하게 되는 경우가 연산 속도가 약간이나마 느려질 수 있게 되고, 또한 포인터가 잘못된 메모리 영역을 가리키고 있는 경우에 포인터를 통한 연산을 하게 되면 바로 공포의 '잘못된 연산을 수행' 창이 뜨게 되는 것이다.

이러한 점을 주의한다면, 포인터는 매우 유용한 도구이다. 실제로 프로그래밍을 할때, 크기가 어느 이상 을 넘어가는 구조체를 함수에서 다른 함수로 넘기는 경우에는 거의 무조건 포인터를 쓰는 것이 정석이다.

포인터의 가장 기본적인 용법은 여기까지이다. 다음에는 포인터의 다른 용도에 대해 알아보도록 하자.

imcgames 의 김학규입니다