61.3 void 포인터 반환하기

지금까지 반환값의 자료형을 정해서 값을 가져왔습니다. 그럼 자료형에 상관없이 값을 꺼내오고 싶다면 어떻게 해야 할까요? 이때는 어떤 자료형으로 된 포인터든 넣을 수 있는 void 포인터를 활용하면 편리합니다.

이번에는 void 포인터를 반환하고 사용하는 방법을 알아보겠습니다. 다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.

return_void_pointer.c

#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일
#include <string.h>    // strcpy 함수가 선언된 헤더 파일

void *allocMemory()    // void 포인터를 반환하는 allocMemory 함수 정의
{
    void *ptr = malloc(100);    // 100바이트만큼 동적 메모리 할당

    return ptr;    // void 포인터 반환
}

int main()
{
    char *s1 = allocMemory();       // void 포인터를 char 포인터에 넣어서 문자열처럼 사용
    strcpy(s1, "Hello, world!");    // s1에 Hello, world! 복사
    printf("%s\n", s1);             // Hello, world!
    free(s1);                       // 동적 메모리 해제

    int *numPtr1 = allocMemory();   // void 포인터를 int 포인터에 넣어서 정수 배열처럼 사용
    numPtr1[0] = 10;                // 첫 번째 요소에 10 저장
    numPtr1[1] = 20;                // 두 번째 요소에 20 저장
    printf("%d %d\n", numPtr1[0], numPtr1[1]); // 10 20
    free(numPtr1);                  // 동적 메모리 해제

    return 0;
}

실행 결과

Hello, world!
10 20

먼저 void *allocMemory()와 같이 함수의 반환값 자료형을 void 포인터로 지정합니다. 그리고 함수 안에서는 void 포인터에 malloc으로 100바이트만큼 메모리를 할당한 뒤 반환합니다.

void *allocMemory()    // void 포인터를 반환하는 allocMemory 함수 정의
{
    void *ptr = malloc(100);    // 100바이트만큼 동적 메모리 할당

    return ptr;    // void 포인터 반환
}

void 포인터는 강제로 변환을 하지 않아도 다양한 형태의 포인터에 넣을 수 있다고 했습니다.

그림 61‑2 void 포인터의 자동 변환

먼저 allocMemory에서 반환된 void 포인터를 문자열 포인터에 넣어서 문자열처럼 사용합니다.

char *s1 = allocMemory();       // void 포인터를 char 포인터에 넣어서 문자열처럼 사용
strcpy(s1, "Hello, world!");    // s1에 Hello, world! 복사
printf("%s\n", s1);             // Hello, world!
free(s1);                       // 동적 메모리 해제

다시 allocMemory에서 반환된 void 포인터를 int 포인터에 넣어서 정수 배열처럼 사용할 수도 있습니다. 단, allocMemory에서 100바이트만큼 메모리를 할당했으므로 100바이트 이상 값을 넣으면 안 됩니다.

int *numPtr1 = allocMemory();    // void 포인터를 int 포인터에 넣어서 정수 배열처럼 사용
numPtr1[0] = 10;                 // 첫 번째 요소에 10 저장
numPtr1[1] = 20;                 // 두 번째 요소에 20 저장
printf("%d %d\n", numPtr1[0], numPtr1[1]);    // 10 20
free(numPtr1);                   // 동적 메모리 해제

allocMemory안에서 malloc를 사용하고 있으므로 allocMemory에서 반환된 포인터를 사용할 때마다 반드시 free 함수로 메모리를 해제해줍니다.

참고 | 코드 줄이기

코드를 줄이려면 ptr 변수를 선언하지 않고, malloc 함수를 호출하면서 바로 반환해도 됩니다. 이렇게 하면 malloc 함수에서 반환된 값을 다시 반환합니다.

void *allocMemory()
{
    return malloc(100);    // malloc 함수를 호출하면서 바로 반환
}