
Python이나 JavaScript로 코딩 여정을 시작했다면, "포인터"라는 단어는 마치 흰 수염을 기른 시스템 엔지니어들만을 위한 신비로운 흑마법처럼 들릴지도 모릅니다. 대학에서 C++를 배웠다 하더라도, 세그멘테이션 폴트(segmentation fault)와 메모리 누수로 고생했던 기억만 남아있을 수도 있죠.
하지만 비밀을 알려드리자면: 포인터는 그저 변수일 뿐입니다. 마법이 아닙니다. 숫자입니다. 단지 그 숫자가 다른 무언가의 주소일 뿐입니다.
포인터를 제대로 이해하려면, 먼저 데이터가 실제로 어디에 사는지 이야기해야 합니다.
코드가 실행될 때, 데이터는 어딘가에 있어야 합니다. 일반적으로 데이터는 스택 또는 힙이라는 두 곳 중 하나에 자리 잡습니다.
스택을 책상 위의 포스트잇 뭉치라고 상상해 보세요.
int a = 10;과 같은 변수가 있다면, 아마 여기에 있을 겁니다. 깔끔하고, 빠르고, 안전하죠.
힙은 거대한 창고입니다.
포인터는 단순히 표지판입니다.
힙의 주소 0x1234에 score = 99라는 변수가 있다면, 포인터는 스택에 있는 아주 작은 변수로 "데이터는 0x1234에 있어요"라고 말해주는 것입니다.
int score = 99; // 실제 값
int *p = &score; // 포인터 'p'는 'score'의 주소를 담고 있음p는 주소입니다 (어디에 있는가?).*p는 값입니다 (안에 무엇이 있는가?).왜 그냥 값을 주고받으면서 언어가 알아서 처리하게 하지 않을까요?
10MB 크기의 이미지가 있다고 상상해 보세요. 만약 process(image) 함수에 이 이미지를 넘길 때 언어가 이미지를 복사한다면, 픽셀을 복사하느라 10MB의 RAM과 CPU 시간을 낭비하게 됩니다.
포인터를 사용하면 주소(8바이트)만 넘기면 됩니다. 함수에게 "이미지는 저쪽에 있으니 가서 봐"라고 말하는 것이죠.
변수를 값으로 함수에 전달하면, 함수는 복제본을 받습니다. 복제본을 변경해도 원본은 그대로입니다. 포인터를 전달하면, 함수는 원본이 어디에 있는지 알게 됩니다. 실제 데이터를 수정할 수 있죠.
연결 리스트, 트리, 그래프—이것들은 다른 데이터 덩어리를 가리키는 포인터를 가진 데이터 덩어리일 뿐입니다. 참조 없이는 이런 구조를 쉽게 만들 수 없습니다.
포인터는 공짜가 아닙니다.
포인터는 여러분의 코드와 하드웨어 사이의 다리입니다. 고수준의 JavaScript나 Python을 작성하더라도, 객체가 내부적으로는 그저 참조(포인터!)라는 것을 이해하면 왜 a = b가 b를 복사하는 것이 아니라 a가 같은 데이터를 가리키게 되는지 이해하는 데 도움이 됩니다.
포인터를 마스터하면 코드가 어떻게 실행되는지 꿰뚫어 볼 수 있는 엑스레이 비전을 갖게 됩니다. "마법"이 아닌 "메모리"를 보게 될 것입니다.
© Melvin Laplanche - All rights reserved.