C와 C++의 void 포인터, 무엇이 다를까?
void 포인터는 C와 C++ 모두에서 사용되는 개념이지만, 두 언어 사이에는 중요한 차이점이 존재합니다. 핵심적인 차이는 암시적 형 변환(implicit conversion)의 허용 여부입니다.
C 언어에서는 void 포인터를 어떤 포인터 타입에든 명시적 캐스팅 없이 자유롭게 할당할 수 있습니다. 반면 C++에서는 타입 안정성을 중시하기 때문에, void 포인터를 다른 포인터 타입에 할당할 때 반드시 명시적 형 변환(explicit typecasting)을 해주어야 합니다.
C에서의 void 포인터 할당
다음 코드는 C 언어에서 문제없이 컴파일되고 실행됩니다.
void *p;
int *int_ptr = p;
C 컴파일러는 void 포인터를 int형 포인터에 암시적으로 변환해 주기 때문에 별도의 캐스팅 없이도 정상적으로 동작합니다.
malloc() 함수와 void 포인터
malloc() 함수는 메모리를 동적으로 할당한 후 그 주소를 void 포인터로 반환합니다. 따라서 C에서는 아래와 같이 캐스팅 없이 바로 받아도 무방합니다.
int *int_ptr = malloc(sizeof(int) * 10);
위 코드에서 malloc()이 반환한 void 포인터가 자동으로 int형 포인터로 암시적 변환됩니다. 물론 명시적으로 캐스팅해도 전혀 문제되지 않습니다.
C와 C++ 양쪽에서 호환되는 코드 작성법
만약 같은 소스 코드를 C와 C++ 두 환경 모두에서 컴파일하고 싶다면, void 포인터를 할당할 때 항상 명시적 형 변환을 사용하는 것이 안전합니다.
void *p;
int *int_ptr = (int *) p;
int *arr_ptr = (int *) malloc(sizeof(int) * 10);
이처럼 (int *) 캐스팅을 추가하면 C++ 컴파일러에서도 오류 없이 컴파일되며, C에서도 여전히 정상적으로 동작합니다.
정리
- C: void 포인터를 다른 포인터 타입에 암시적으로 할당 가능
- C++: void 포인터 할당 시 반드시 명시적 형 변환 필요
- 호환 코드: 명시적 캐스팅을 사용하면 C와 C++ 모두에서 동작
C++가 이런 규칙을 둔 이유는 타입 안정성을 강화하여 개발자의 실수로 인한 버그를 줄이기 위함입니다. void 포인터는 실제 데이터 타입 정보를 가지고 있지 않기 때문에, C++에서는 프로그래머가 의도를 명확히 드러내도록 요구하는 것입니다.