63.2 void 포인터 매개변수 사용하기

void 포인터 매개변수를 사용하면 자료형 변환을 하지 않아도 모든 자료형을 함수에 넣을 수 있습니다. 이번에는 char, int, float형을 매개변수로 받아서 값을 서로 바꿔보겠습니다.

parameter_void_pointer.c

#include <stdio.h>

enum TYPE {
    TYPE_CHAR,
    TYPE_INT,
    TYPE_FLOAT
};

void swapValue(void *ptr1, void *ptr2, enum TYPE t)    // 반환값 없음, void 포인터 매개변수 두 개와
{                                                      // 변수의 자료형을 알려줄 열거형을 받음
    switch (t)
    {
    case TYPE_CHAR:    // 문자면 char *로 변환한 뒤 역참조하여 값을 서로 바꿈
    {
        char temp;
        temp = *(char *)ptr1;
        *(char *)ptr1 = *(char *)ptr2;
        *(char *)ptr2 = temp;
        break;
    }
    case TYPE_INT:     // 정수면 int *로 변환한 뒤 역참조하여 값을 서로 바꿈
    {
        int temp;
        temp = *(int *)ptr1;
        *(int *)ptr1 = *(int *)ptr2;
        *(int *)ptr2 = temp;
        break;
    }
    case TYPE_FLOAT:    // 실수면 float *로 변환한 뒤 역참조하여 값을 서로 바꿈
    {
        float temp;
        temp = *(float *)ptr1;
        *(float *)ptr1 = *(float *)ptr2;
        *(float *)ptr2 = temp;
        break;
    }
    }
}

int main()
{
    char c1 = 'a';
    char c2 = 'b';
    swapValue(&c1, &c2, TYPE_CHAR);       // 변수의 메모리 주소와 TYPE_CHAR를 넣음
    printf("%c %c\n", c1, c2);            // b a: swapValue에 의해서 값이 서로 바뀜

    int num1 = 10;
    int num2 = 20;
    swapValue(&num1, &num2, TYPE_INT);   // 변수의 메모리 주소와 TYPE_INT를 넣음
    printf("%d %d\n", num1, num2);       // 20 10: swapValue에 의해서 값이 서로 바뀜

    float num3 = 1.234567f;
    float num4 = 7.654321f;
    swapValue(&num3, &num4, TYPE_FLOAT);  // 변수의 메모리 주소와 TYPE_FLOAT를 넣음
    printf("%f %f\n", num3, num4);        // 7.654321f 1.234567: 
                                          // swapValue에 의해서 값이 서로 바뀜

    return 0;
}

실행 결과

b a
20 10
7.654321 1.234567

swapValue 함수에 매개변수를 void 포인터 두 개로 지정합니다. 단, void 포인터는 역참조를 할 수 없으므로 어떤 자료형으로 역참조할지 알려주기 위해 TYPE 열거형도 함께 받습니다. 함수 안에서는 TYPE에 따라 각 자료형의 포인터로 변환한 뒤 역참조하여 값을 서로 바꿉니다.

void swapValue(void *ptr1, void *ptr2, enum TYPE t)    // 반환값 없음, void 포인터 매개변수 두 개와
{                                                      // 변수의 자료형을 알려줄 열거형을 받음
    switch (t)
    {
    case TYPE_CHAR:    // 문자면 char *로 변환한 뒤 역참조하여 값을 서로 바꿈
    {
        char temp;
        temp = *(char *)ptr1;
        *(char *)ptr1 = *(char *)ptr2;
        *(char *)ptr2 = temp;
        break;
    }
    case TYPE_INT:     // 정수면 int *로 변환한 뒤 역참조하여 값을 서로 바꿈
    {
        int temp;
        temp = *(int *)ptr1;
        *(int *)ptr1 = *(int *)ptr2;
        *(int *)ptr2 = temp;
        break;
    }
    case TYPE_FLOAT:   // 실수면 float *로 변환한 뒤 역참조하여 값을 서로 바꿈
    {
        float temp;
        temp = *(float *)ptr1;
        *(float *)ptr1 = *(float *)ptr2;
        *(float *)ptr2 = temp;
        break;
    }
    }
}

swapValue 함수를 사용할 때는 자료형 변환을 하지 않아도 다양한 자료형의 포인터(메모리 주소)를 넣을 수 있습니다. 여기서는 & (주소 연산자)를 사용하여 char, int, float형 변수의 주소를 구해서 swapValue 함수에 넣었습니다. 물론 어떤 자료형인지 알려줘야 하므로 TYPE 열거형 값도 넣어줍니다.

char c1 = 'a';
char c2 = 'b';
swapValue(&c1, &c2, TYPE_CHAR);        // 변수의 메모리 주소와 TYPE_CHAR를 넣음
printf("%c %c\n", c1, c2);             // b a: swapValue에 의해서 값이 서로 바뀜

int num1 = 10;
int num2 = 20;
swapValue(&num1, &num2, TYPE_INT);     // 변수의 메모리 주소와 TYPE_INT를 넣음
printf("%d %d\n", num1, num2);         // 20 10: swapValue에 의해서 값이 서로 바뀜

float num3 = 1.234567f;
float num4 = 7.654321f;
swapValue(&num3, &num4, TYPE_FLOAT); // 변수의 메모리 주소와 TYPE_FLOAT를 넣음
printf("%f %f\n", num3, num4);       // 7.654321f 1.234567: 
                                     // swapValue에 의해서 값이 서로 바뀜

void 포인터 매개변수에는 변수의 메모리 주소뿐만 아니라 메모리를 할당한 포인터도 넣을 수 있습니다. 또한, 일반 자료형의 포인터뿐만 아니라 구조체, 공용체, 열거형 등의 포인터도 넣을 수 있습니다.