전 포스팅에서 알아봤듯, 자료형에 *를 붙여서 자료형에 알맞는 포인터 변수를 만들어줬다. 그런데, void 포인터를 사용하면 어떤 자료형이든 간에 활용할 수 있다. 따라서 범용포인터라고 불리기도 한다. 즉, 직접 자료형을 변환하지 않아도 암시적으로 자료형이 아래와 같이 변환된다.
자료형이 정해지지 않아서, 값을 가져오거나 저장할 크기도 정해지지 않았다. 그래서 역참조를 할 수가 없다!
역참조도 못하는 void 포인터를 뭐하러 쓰려는 걸까? 다양한 활용도를 가지기 때문이다. 예를 들자면 함수에서 다양한 자료형을 받아들일 때, 함수의 반환 포인터를 다양한 자료형으로 된 포인터에 저장할 때, 자료형을 숨기고 싶을 때 사용한다고 한다... 파이팅!
4-5일 전 포스팅한 글에 swap()함수를 통해서 포인터의 활용을 알아봤었다. 포인터를 통해서 함수 안에서 여러 변수의 값을 변형시킬 수 있었다.
void 포인터를 활용하면 더 효율적으로 일할 수 있다. 즉, 자료형을 변환하지 않아도 모든 자료형 포인터들을 함수에 넣을 수 있는 것이다.
예를 들면, 아래와 같은 함수의 매개변수를 void 포인터로 받을 수 있다. void 포인터는 설명했다시피 역참조는 불가하므로 함수 안에서 다시 형 변환을 통해서만 값을 건드릴 수 있다.
void swapValue(void *ptr1, void *ptr2, enum TYPE t) //반환값 없고, 매개변수 void 포인터
{
...
char temp;
temp = *(char *)ptr1;
*(char *)ptr1 = *(char *)ptr2;
*(char *)ptr2 = temp;
...
}
위와 같이 내부에서 (char *) 등을 활용하여 형 변환을 해줘야 한다.
형 변환은 아래와 같이 " (자료형 *) 포인터 "로 할 수 있다.
(char *) numPtr;
이 때, 유의해야할 점은 형 변환해주는 포인터가 가리키고 있던 기존 자료형을 잘 봐야한다.
void 포인터의 형 변환은 위에도 잠깐 나타냈지만, 역참조(*)하고자 하는 자료형에 맞추어 형 변환을 해주고 역참조를 하면 된다.
#include <stdio.h>
int main()
{
int num1 = 10;
float num2 = 3.5f;
char c1 = 'a';
void *ptr;
ptr = &num1; // num1의 메모리 주소를 void 포인터 ptr에 저장
// printf("%d\n", *ptr); // 컴파일 에러
printf("%d\n", *(int *)ptr); // 10: void 포인터를 int 포인터로 변환한 뒤 역참조
ptr = &num2; // num2의 메모리 주소를 void 포인터 ptr에 저장
// printf("%f\n", *ptr); // 컴파일 에러
printf("%f\n", *(float *)ptr); // 3.500000: void 포인터를 float 포인터로 변환한 뒤 역참조
ptr = &c1; // c1의 메모리 주소를 void 포인터 ptr에 저장
// printf("%c\n", *ptr); // 컴파일 에러
printf("%c\n", *(char *)ptr); // a: void 포인터를 char 포인터로 변환한 뒤 역참조
}
멋쟁이씨 호ㅏ이팅💓💓💓 우다가 가즈아!!!!!!!