-
포인터도 타입이 필요한 이유Programming🧑💻/Cpp 2025. 1. 31. 12:33
포인터 연산
포인터 연산에서 중요한 점은 포인터의 타입에 따라 실제 증감되는 메모리 주소의 크기가 달라진다는 것입니다.
char* ptr1 = (char*)1000; // char는 1바이트 int* ptr2 = (int*)1000; // int는 4바이트 double* ptr3 = (double*)1000; // double은 8바이트 ptr1++; // 주소값: 1001 ptr2++; // 주소값: 1004 ptr3++; // 주소값: 1008
- char 포인터는 1바이트씩 증가
- int 포인터는 4바이트씩 증가
- double 포인터는 8바이트씩 증가
즉, ptr++ 연산을 수행할 때 실제로는 다음과 같은 계산이 이루어집니다.
새로운주소 = 현재주소 + (sizeof(포인터타입) * 1)
포인터 타입을 제한하는 이유
C++에서는 int 타입의 변수는 int* 타입의 포인터에, char 타입의 변수는 char* 타입의 포인터에만 저장할 수 있도록 제한합니다.
포인터가 단순히 메모리 주소만을 저장하는데 왜 이런 제한이 필요할까요?
이는 포인터의 역참조(Dereferencing) 연산과 관련이 있습니다.
역참조를 통해 포인터가 가리키는 메모리 주소의 값을 읽거나 수정할 때, 시스템은 해당 메모리 위치에서 얼마만큼의 바이트를 읽어야 할지 알아야 합니다.
int main() { // 1. int 변수 선언 및 초기화 int a = 1025; // 이진수로 00000000 00000000 00000100 00000001 // 2. int 포인터로 접근 int* p_int = &a; cout << "Value using int pointer: " << *p_int << endl; // 출력: 1025 // 3. char 포인터로 잘못 접근하는 경우 char* p_char = (char*)&a; cout << "Value using char pointer: " << (int)*p_char << endl; // 출력: 1 return 0; }
int a = 1025
- int 타입은 일반적으로 4바이트(32비트) 메모리를 할당받습니다
- 1025는 이진수로 00000000 00000000 00000100 00000001로 저장됩니다
int* p_int = &a
- p_int는 a의 메모리 주소를 저장합니다
*p_int
로 역참조할 때 시스템은 이 주소에서 4바이트를 읽습니다- 따라서 올바른 값 1025를 얻을 수 있습니다
char* p_char = (char*)&a
- char 포인터로 캐스팅하면 시스템은 이 주소에서 1바이트만 읽습니다
- 첫 번째 바이트인 00000001만 읽게 되어 값 1을 얻게 됩니다
이처럼 포인터 타입은 역참조 시 얼마만큼의 메모리를 읽어야 하는지를 결정합니다. 잘못된 타입의 포인터를 사용하면 데이터를 부분적으로만 읽거나, 잘못된 방식으로 해석할 수 있습니다.
void 포인터
예외적으로 C++에는 모든 타입의 주소를 저장할 수 있는 특별한 포인터가 있습니다. 바로 void 포인터(void*)입니다.
int num = 10; char ch = 'A'; double pi = 3.14; // void 포인터는 어떤 타입의 주소든 저장 가능 void* ptr; ptr = # // int 주소 저장 ptr = &ch; // char 주소 저장 ptr = π // double 주소 저장
하지만 void 포인터는 다음과 같은 중요한 제약사항이 있습니다
1. 직접 역참조가 불가능합니다
void* ptr = &a *ptr; // 컴파일 에러!
2. 포인터 연산을 할 수 없습니다
void* ptr = # ptr++; // 컴파일 에러!
이러한 제약이 있는 이유는 앞서 설명했던 것처럼 시스템이 메모리에서 얼마만큼의 크기를 읽어야 할지 알 수 없기 때문입니다.
따라서 void 포인터를 사용할 때는 반드시 적절한 타입으로 변환 후 사용해야 합니다
int num = 42; void* void_ptr = # // int 포인터로 캐스팅 후 사용 int* int_ptr = static_cast<int*>(void_ptr); cout << *int_ptr << endl; // 42 출력
'Programming🧑💻 > Cpp' 카테고리의 다른 글
콜 스택 동작을 통해 알아보는 함수 호출 (0) 2025.02.04 포인터의 크기는 어떻게 결정될까? (0) 2025.02.03 이중 포인터 (0) 2025.02.01 변수와 포인터 (0) 2025.01.30