포인터
포인터는 컴퓨터 과학에서 메모리 주소를 값으로 가지는 변수를 의미한다. 포인터는 특정 변수의 위치를 가리키거나, 동적으로 할당된 메모리 공간에 접근하는 데 사용된다. 프로그래밍 언어에 따라 명시적으로 포인터를 지원하는 언어(C, C++, Go 등)와, 내부적으로 포인터 개념을 활용하지만 직접적인 조작을 제한하는 언어(Java, Python 등)가 존재한다.
개념
포인터는 메모리 주소를 담는 변수이므로, 일반적인 변수와는 다른 방식으로 동작한다. 일반 변수는 데이터 값을 저장하는 반면, 포인터는 해당 데이터가 저장된 메모리 상의 위치를 저장한다. 이러한 특징 때문에 포인터를 사용하면 다음과 같은 작업이 가능하다.
- 직접적인 메모리 접근: 포인터를 통해 특정 메모리 위치에 직접 접근하여 값을 읽거나 쓸 수 있다.
- 함수 인자로 값 전달 대신 주소 전달: 함수에 인자를 전달할 때, 값 자체를 복사하는 대신 포인터를 전달하면 원본 데이터를 변경할 수 있다. 이는 메모리 사용량을 줄이고 성능을 향상시키는 데 도움이 된다.
- 동적 메모리 할당: 프로그램 실행 중에 필요한 메모리 공간을 동적으로 할당하고 해제할 수 있다.
malloc
,new
등의 함수를 사용하여 메모리를 할당받고, 할당된 메모리의 주소를 포인터에 저장하여 사용한다. - 자료 구조 구현: 연결 리스트, 트리 등 복잡한 자료 구조를 구현하는 데 필수적인 요소이다. 각 노드는 데이터와 다음 노드의 주소를 저장하는 포인터로 구성될 수 있다.
장점 및 단점
포인터는 강력한 기능이지만, 잘못 사용하면 프로그램 오류를 유발할 수 있다.
- 장점:
- 메모리 효율성 향상
- 성능 향상
- 유연한 자료 구조 구현
- 단점:
- 메모리 누수 발생 가능성
- 댕글링 포인터(dangling pointer) 문제 발생 가능성 (이미 해제된 메모리를 가리키는 포인터)
- 널 포인터 역참조 오류 발생 가능성 (NULL 또는 nullptr를 가리키는 포인터를 사용하려 할 때 발생)
- 코드의 복잡성 증가
사용 시 주의사항
포인터를 사용할 때는 다음과 같은 사항에 주의해야 한다.
- 포인터를 초기화하지 않고 사용하지 않도록 한다. 초기화되지 않은 포인터는 임의의 메모리 위치를 가리키게 되어 예상치 못한 오류를 발생시킬 수 있다.
- 할당된 메모리를 사용 후에는 반드시 해제해야 한다. 그렇지 않으면 메모리 누수가 발생할 수 있다.
- 포인터 연산을 수행할 때 메모리 범위를 벗어나지 않도록 주의해야 한다.
- 댕글링 포인터를 사용하지 않도록 주의해야 한다.
- 널 포인터 역참조 오류를 방지하기 위해 포인터가 유효한 메모리 주소를 가리키는지 확인 후 사용해야 한다.
관련 용어
- 역참조 (dereference): 포인터가 가리키는 메모리 위치의 값을 얻는 연산.
- 메모리 누수 (memory leak): 할당된 메모리를 해제하지 않아 프로그램이 사용할 수 있는 메모리 공간이 줄어드는 현상.
- 댕글링 포인터 (dangling pointer): 이미 해제된 메모리 영역을 가리키는 포인터.
- 널 포인터 (null pointer): 아무것도 가리키지 않는 포인터. 주로 0 또는 NULL, nullptr로 표현된다.
- 참조 (reference): C++에서 포인터와 유사하게 사용되는 개념으로, 변수의 별칭을 만드는 데 사용된다. 포인터와 달리 항상 초기화되어야 하며, 다른 변수를 가리키도록 변경할 수 없다.