Void 포인터 동적할당 - void pointeo dongjeoghaldang

* C에서 동적메모리 할당을 위해 우리는 malloc 또는 calloc을 보통 쓰곤 한다. 여기서는 이 함수들보다는 void 포인터에 대해서 포커싱을 두려 한다.

1. void 포인터란?

 - void 포인터는 타입이 없는 포인터이다. 포인터는 주소값을 저장하는데, 보통 타입이 있어야 한다. 예를 들어서 int형 포인터 변수에 double 변수의 주소값을 저장하거나 한다면 이는 크나큰 메모리 침범 및 오류가 발생할 수 있다. (역시 이러한 이야기는 여기서는 제외합니다.) 따라서 정확한 타입의 포인터 변수에 해당되는 정확한 타입의 변수의 주소값을 넣어주어야 한다. 그런데 void 포인터는 타입이 없다. 이것은 무슨의미 일까?

Void 포인터 동적할당 - void pointeo dongjeoghaldang

바로 void 포인터는 그 어떤 타입으로든 원하는대로 캐스팅(casting)하여 사용이 가능하다. 라는 의미이다. 자 이게 무슨말이고, 왜 그렇게 되어야 하는지 동적메모리할당을 통해서 간단하게 살펴보자.

2. 동적메모리할당

 - C에서 사용하는 동적메모리할당의 가장 흔한 malloc을 가지고 따라가보자.

malloc의 원형은 아래와 같다.

void* malloc(size_t size);

size는 당연히 할당하자고 하자는 메모리의 크기일 것이다. 그런데 보이는가? 리턴타입이 바로 void* 이다.

이 함수의 기능을 말로 풀어보자면,

할당하고자 하는 메모리가 있는데, malloc을 이용해서 원하는 만큼의 크기를 전달해준다. 그러면 malloc함수는 현재 메모리를 검사하여 원하는 만큼의 빈공간이 있는 곳을 찾아낸다. 이후에 그만큼의 메모리를 다른데서 사용하지 못하도록 할당한 후에 그 메모리의 첫번째 주소값을 돌려준다. 자 이와 같이 될건데, 바로 그 돌려주는 주소값!!!!. 이것이 void* 형태이다. 즉 따로 정해진 타입이 없다. 이것은 malloc함수는 메모리를 할당하고 그 첫번째의 주소값을 돌려줄뿐, 그 주소에 접근해서 어떻게 데이터를 저장하고 읽어오고 하는 등의 사용방법은 할당한 사람에게 맡긴다는 의미이다. 만약 이게 정해져있다면, 리턴타입이 여러개여야 할 것이다. char, int, double, 각종 구조체타입등 수많은 타입들을 다 만들어둘수가 없다. 몇몇 primitive타입들은 만들어둘수도 있으나, 사용자가 정의하는 구조체타입은 무한하기때문에 정의해두는게 불가능하다. 그래서 void*가 필요한 것이다.

예를 들어보자.

malloc(sizeof(int) * 4); 라고 해보자. sizeof()함수는 말그대로 사이즈를 리턴한다. int의 사이즈는 4바이트며, 4 * 4 이므로 16바이트를 할당하게 된다. 우리는 여기서 16바이트를 할당해서 4개의 int값을 저장하고자 하는 의도로 메모리를 할당한 것이다. 따라서 malloc 함수가 int*를 리턴해주면, 리턴되는 주소값부터 16바이트가 우리가 사용할 영역이 된다. 그러나 처음부터 말한것처럼 malloc는 사용자가 int값을 저장하려고 한건지, char값을 저장하려고 한건지 전혀 알지 못한다. 그렇기 때문에 malloc은 단순하게 void* 를 줄테니 니가 알아서 사용해라. 하는 것이다. 즉 casting을 통하게 되면 void*는 어떤 형태의 포인터이든 변신이 가능하다. 그야말로 만능형이다.

Void 포인터 동적할당 - void pointeo dongjeoghaldang

3. 동적메모리할당과 타입캐스팅.

- 자 이제, 정확하게 사용하는 법을 다시 알아보자.

malloc을 이용해 메모리를 할당하면 void*를 리턴하게 되므로, 우리가 사용하고자 하는 타입으로 적절히 캐스팅을 하면 된다.

예를 들어,

int* a;

a = (int*)malloc(sizeof(int) * 10);

위와 같이 한다면 a는 10개의 int를 저장할수 있는 배열을 선언한 것과 같은 원리가 된다.

사용방법은 여기서 논외이므로 포인터파트에서 다루는게 좋을것같다.

결론적으로 왼쪽의 타입과 캐스팅하는 타입이 동일해야만 한다. 그래야만, 적절한 공간에 적절한 데이터를 쓰게 된다.

1바이트 char형 메모리에 double타입의 데이터를 쓰게된다든지 하는 오류를 방지하는 것이다. (허용되지 않은 메모리를 사용할 경우 매우 큰일이 벌어질수 있다. 이때문에 포인터가 강력하기도 하지만 어려운 것이다.)

하나만 더 예를 들어보자. 구조체를 선언했다고 가정하자.

struct AAA

{

int a;

int b;

char c;

double d;

}

이 구조체 10개를 저장할 메모리 공간을 어떻게 할당해야 할까?

struct AAA* p;

p = (struct AAA*)malloc(sizeof(struct AAA) * 10)); <-- 방법을 알겠는가??

Void 포인터 동적할당 - void pointeo dongjeoghaldang

- C언어 과제대행, 과외(대전, 온라인) 해드립니다. 자세한 내용은 쪽지 또는 메일로 문의주세요.

 (공지사항 참조) 

Void 포인터 동적할당 - void pointeo dongjeoghaldang