✒️ 0. 들어가기 전
포인터는 C와 C++와 같은 저수준 프로그래밍 언어에서 메모리를 직접 다루는 강력한 도구이다.
이 글에서는 C++ 언어로 포인터의 개념, 메모리와의 관계, 그리고 실제 사용에 살펴보자.
✒️ 1. 메모리와 주소
컴퓨터의 메모리는 1바이트 크기의 셀들이 연속적으로 나열된 구조이다.
각 셀은 고유한 주소를 가지며, 이 주소를 통해 메모리에 접근한다.
예를 들어, 'int i;'라는 선언은 4바이트(일반적인 int 크기)의 메모리 영역을 예약한다.
이때 변수 i의 주소는 이 4바이트 중 첫 번째 바이트의 주소를 가르킨다.
그럼 값이 아닌, 이 주소를 직접 출력해보려면 어떻게 해야할까?
C++에서는 '&' 연산자를 사용하여 변수의 메모리 주소를 얻을 수 있다.
int i = 0;
cout << &i; // i의 메모리 주소 출력
* 0x0000은 예시일 뿐, 실제 출력하면 다르게 나올 것이다~
그렇다면 이 번수에 실제 값이 "0"을 할당한다면??
방금 예약한 메모리 영역에 해당 값을 저장하게 된다.
✒️ 2. 포인터의 개념
포인터는 다른 변수의 메모리 주소를 저장하는 변수이다.
포인터를 통해 우리는 메모리를 직접 조작할 수 있으며, 이는 동적 메모리 할당, 효율적인 데이터 전달, 복잡한 데이터 구조 구현 등에 사용된다.
int* ptr; // int 타입을 가리키는 포인터
string* strPtr; // string 타입을 가리키는 포인터
자바, 파이썬, 자바스크립트라는 언어로는 개발자가 직접 변수에 메모리를 할당하거나 해제할 수 없고 가비지컬렉터를 통해 이를 수행한다.
💡 포인터의 크기
포인터의 크기는 OS의 아키텍처에 따라 결정된다.
32비트 시스템에서는 4바이트, 64비트 시스템에서는 8바이트이다. 이는 포인터가 가리키는 데이터 타입과 무관하다.
✒️ 3. 역참조 연산자
'*' 연산자는 포인터가 가리키는 메모리 위치의 값을 얻는 데 사용된다.
이를 역참조(dereferencing)라고 한다.
int x = 10;
int* ptr = &x;
cout << *ptr; // 10 출력
✒️ 4. Array to Pointer Decay
C++에서 배열 이름은 특정 상황에서 자동으로 포인터로 변환된다.
이를 "array to pointer decay"라고 한다.
이 현상으로 인해 배열의 이름은 배열의 첫 번째 요소의 주소로 취급된다.
int arr[3] = {1, 2, 3};
int* ptr = arr; // arr은 &arr[0]과 동일
✒️ 5. 포인터 연산
포인터에 정수를 더하거나 빼면, 해당 타입의 크기만큼 주소가 이동한다.
int arr[3] = {1, 2, 3};
int* ptr = arr;
cout << *(ptr + 1); // 2 출력 (arr[1]과 동일)
💡 포인터와 const
const 키워드를 사용하여 포인터가 가리키는 값 또는 포인터 자체를 상수로 만들 수 있다.
const int* ptr1; // ptr1이 가리키는 값을 변경할 수 없음
int* const ptr2 = &someInt; // ptr2 자체를 변경할 수 없음
💡 널 포인터
포인터가 아무것도 가리키지 않음을 나타내기 위해 널 포인터를 사용한다.
int* ptr = nullptr; // C++11 이후
📝 면접 예상 질문
Q1: 포인터와 참조자(reference)의 차이점은 무엇인가요?
A1: 포인터는 변수의 메모리 주소를 저장하는 별도의 변수이며, 널값을 가질 수 있고 재할당이 가능합니다. 반면 참조자는 변수의 별칭으로, 선언 시 초기화해야 하며 재할당이 불가능합니다.
Q2: "array to pointer decay"란 무엇이며, 어떤 상황에서 주의해야 하나요?
A2: "Array to pointer decay"는 배열이 포인터로 암시적 변환되는 현상입니다. 이로 인해 배열의 크기 정보가 손실될 수 있어, 함수에 배열을 전달할 때 크기 정보를 별도로 전달해야 할 수 있습니다.
Q3: 포인터를 사용할 때의 주요 위험성은 무엇인가요?
A3: 주요 위험성으로는 널 포인터 역참조, 댕글링 포인터(해제된 메모리를 가리키는 포인터) 사용, 버퍼 오버플로우 등이 있습니다. 이러한 문제들은 프로그램 크래시나 보안 취약점을 유발할 수 있습니다.
(본인은 Java 개발자로 포인터에 대해 간단하게 알아보았다!)