서론: 마법사의 지팡이, 포인터
C언어를 배우는 수많은 학생이 "포인터에서 좌절했다"고 말합니다. 도대체 포인터가 뭐길래 사람들을 괴롭히는 걸까요? 제가 NASA에서 근무할 때, 선임 엔지니어는 포인터를 '마법사의 지팡이'라고 불렀습니다.
지팡이 끝이 가리키는 곳에 번개가 떨어지듯, 포인터는 메모리의 특정 위치를 직접 가리켜 그곳의 데이터를 조작하는 기술입니다. 이 개념이 없으면 우리는 하드웨어의 깊은 곳(운영체제, 드라이버 등)에 절대 접근할 수 없습니다.
오늘 6편에서는 복잡한 문법 대신, 포인터가 왜 필요한지, 그리고 그것이 물리적으로 어떤 의미를 갖는지 '좌표'와 '지도'의 개념으로 아주 쉽게 설명해 드리겠습니다.
본론 1: 데이터(내용물) vs 주소(위치)
포인터를 이해하려면 '값'과 '주소'를 철저히 구분해야 합니다.
거대한 물류 창고를 상상해 봅시다.
- 변수 (Variable): 창고 안의 101호 상자입니다. 그 안에 '황금(데이터)'이 들어있습니다.
- 포인터 (Pointer): 창고 안의 상자가 아닙니다. "101호에 황금이 있다"라고 적힌 쪽지(지도)입니다.
일반 변수는 상자 안의 내용물(황금)을 보여주지만, 포인터 변수는 그 상자가 어디에 있는지(101호)를 알려줍니다. 즉, 포인터는 데이터를 담는 그릇이 아니라, 데이터가 사는 곳의 좌표(Address)를 담는 변수입니다.
본론 2: 암호를 해독하라 (&와 *)
C언어에서 포인터를 쓸 때 등장하는 기호 &와 *는 딱 두 마디로 정의할 수 있습니다.
1. & (주소 연산자): "너 어디 살아?"
변수 앞에 &를 붙이면(예: &a), 그 변수의 실제 메모리 주소를 알려줍니다.
"야, 변수 a! 너 메모리 몇 번지에 살고 있어?" 라고 묻는 것과 같습니다.
2. * (참조 연산자): "그곳으로 가라!"
포인터 변수 앞에 *를 붙이면(예: *p), 그 주소로 순간 이동을 합니다.
"포인터 p야, 네가 가리키는 주소(101호)로 가서 문을 열고 내용물을 가져와!" 라는 명령입니다.
본론 3: 왜 굳이 포인터를 쓰는가? (NASA의 이유)
"그냥 변수 쓰면 되지, 왜 복잡하게 주소를 쓰나요?" 가장 중요한 이유는 효율성입니다.
우주선 설계도 데이터가 100GB라고 가정해 봅시다. 이 설계도를 A라는 함수에서 B라는 함수로 전달해야 합니다.
- 포인터를 안 쓸 때 (Call by Value): 100GB짜리 설계도를 통째로 복사해서 전달합니다. 메모리는 터져 나가고, 복사하는 데 엄청난 시간이 걸립니다.
- 포인터를 쓸 때 (Call by Reference): 설계도는 그대로 두고, 설계도가 있는 '위치(주소)가 적힌 쪽지' 한 장만 건네줍니다. 받는 사람은 그 주소로 찾아와서 설계도를 보면 됩니다.
쪽지(주소)의 크기는 고작 4바이트(또는 8바이트)입니다. 100GB를 복사하는 대신 4바이트만 전달하면 되니, 속도와 메모리 효율이 수만 배 좋아집니다. 이것이 시스템 프로그래밍에서 포인터가 필수인 이유입니다.
결론: 하드웨어를 장악하는 열쇠
포인터는 어렵습니다. 잘못 쓰면 엉뚱한 주소를 건드려 프로그램이 뻗어버리는(Segmentation Fault) 위험한 도구이기도 합니다. 하지만 이 위험을 감수하는 자만이 하드웨어의 진정한 주인이 될 수 있습니다.
포인터를 이해했다는 것은, 이제 여러분이 메모리라는 광활한 우주를 마음대로 여행할 수 있는 좌표(Coordinate)를 손에 넣었다는 뜻입니다.
다음 [Part 7. 배열(Array)의 물리학] 편에서는, 이 포인터 개념을 활용하여 수많은 데이터를 연속적으로 다루는 '배열'의 비밀, 그리고 배열과 포인터가 사실은 한 몸이라는 충격적인 사실에 대해 알아보겠습니다.