C++에서 포인터는 변수의 메모리 주소를 저장하는 특수한 변수입니다. 컴퓨터는 데이터를 저장하기 위해 메모리를 사용하며, 각 메모리 공간은 고유한 주소를 가지고 있습니다. 포인터는 이러한 메모리 주소를 저장해 해당 메모리 공간에 직접 접근할 수 있도록 해줍니다. 이를 통해 프로그램은 데이터를 효율적으로 관리하고 성능을 향상시킬 수 있습니다.
포인터는 변수의 값을 직접 읽거나 변경하는 데 사용되며, 함수에 데이터를 전달할 때 메모리를 효율적으로 관리하는 데 유용합니다. C++에서 포인터를 올바르게 이해하고 사용하는 것은 매우 중요합니다.
포인터를 선언할 때는 변수 타입 앞에 별표(*)를 붙입니다. 예를 들어, int 타입의 포인터를 선언하려면 int *ptr과 같이 작성합니다. 포인터는 해당 타입의 메모리 주소만 저장할 수 있습니다.
int a = 100;
int* ptr = &a;
cout << a << endl; // 100
cout << ptr << endl; // a의 주소값 출력
cout << *ptr << endl; // 100 (ptr이 가리키는 값)
포인터는 메모리 주소를 가리키므로, 주소를 이동하거나 값을 읽고 변경하는 연산이 가능합니다. ptr + 1은 단순히 1을 더하는 것이 아니라, 포인터가 가리키는 데이터 타입의 크기만큼 주소를 이동합니다. 예를 들어, int 타입은 보통 4바이트이므로 ptr + 1은 현재 주소에서 4바이트 이동합니다.
// 예: 포인터가 0x1000을 가리킬 때
| 0x1000 | 0x1001 | 0x1002 | 0x1003 | 0x1004 |
ptr + 1은 0x1004를 가리키게 됩니다.
배열의 이름은 배열의 첫 번째 요소의 주소를 나타내므로, 포인터 변수에 배열 이름을 할당하면 배열의 첫 번째 요소를 가리키는 포인터가 됩니다.
int arr[5] = {10, 20, 30, 40, 50};
int* ptr = arr; // arr은 첫 번째 요소의 주소를 가리킴
위 코드에서 arr은 arr[0]의 주소를 가리키며, ptr = arr은 ptr이 arr[0]을 가리키도록 설정하는 것과 동일합니다.
cout << *ptr << endl; // 10 (arr[0])
cout << *(ptr + 1) << endl; // 20 (arr[1])
cout << *(ptr + 2) << endl; // 30 (arr[2])
포인터의 잘못된 사용은 프로그램에 심각한 오류를 유발할 수 있습니다.
널 포인터는 초기화되지 않거나 유효하지 않은 주소를 가리키는 포인터입니다. 널 포인터를 참조하면 **런타임 오류(Segmentation Fault)**가 발생합니다.
int* ptr = nullptr;
*ptr = 10; // 잘못된 참조, 프로그램 비정상 종료
널 포인터를 사용할 때는 반드시 널 여부를 확인해야 합니다.