Menu
Coddy logo textTech

제네릭 스왑

Coddy C 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 61개 중 51번째.

프로그래밍에서 흔히 수행하는 작업 중 하나는 두 값을 교환하는 것입니다. 일반적으로는 각 타입마다 별도의 swap 함수를 작성합니다. int용 하나, double용 또 하나 등을 작성하는 식입니다. 하지만 void*memcpy를 사용하면 어떤 두 변수든 교환할 수 있는 단일 함수를 작성할 수 있습니다.

핵심 통찰은 교환이 단지 바이트를 이리저리 옮기는 작업이라는 것입니다. 데이터의 크기를 알고 있다면 실제 유형을 몰라도 바이트를 복사할 수 있습니다. 함수 시그니처는 다음과 같습니다:

void generic_swap(void* a, void* b, size_t size);

size 매개변수는 function이 이동할 bytes의 개수를 알려 줍니다. 내부에서는 temporary buffer와 memcpy<string.h>에서 사용하여 bytes를 섞습니다:

void generic_swap(void* a, void* b, size_t size) {
    char temp[size];      // 임시 버퍼
    memcpy(temp, a, size);  // temp = a
    memcpy(a, b, size);     // a = b
    memcpy(b, temp, size);  // b = temp
}

이제 이 단일 함수는 모든 type에서 작동합니다:

int x = 5, y = 10;
generic_swap(&x, &y, sizeof(int));
// x는 이제 10이고, y는 이제 5입니다
double p = 3.14, q = 2.71;
generic_swap(&p, &q, sizeof(double));
// p는 이제 2.71, q는 이제 3.14

void*size_t를 사용하는 이 패턴은 C의 표준 라이브러리가 qsortbsearch와 같은 제네릭 함수를 구현하는 방식입니다.

challenge icon

챌린지

쉬움

void* 포인터와 memcpy의 강력한 기능을 사용하여, 자료형과 관계없이 두 변수의 값을 교환할 수 있는 범용 swap 유틸리티를 만들어 봅시다.

코드를 세 개의 파일로 구성합니다:

  • swap.h: 두 개의 void* 포인터와 교환할 데이터의 크기를 나타내는 size_t 매개변수를 받는 generic_swap function을 Declare합니다. include guard도 잊지 마세요!
  • swap.c: generic_swap function을 Implement합니다. temporary buffer와 memcpy를 사용하여 두 메모리 위치 사이에서 bytes를 이동합니다. three-step swap pattern을 Remember하세요: first value를 temp로 Copy하고, second를 first로 Copy한 다음, temp를 second로 Copy합니다.
  • main.c: 다양한 data type에서 generic swap이 작동하는 모습을 보여 줍니다. type indicator(i는 정수, d는 double)를 읽은 다음 두 값을 읽습니다. 적절한 type의 두 변수를 만들고, generic_swap function을 사용하여 swap한 뒤, swap 후 두 값을 모두 출력합니다.

프로그램은 세 개의 입력을 받습니다:

  1. type indicator: 정수는 i, double은 d
  2. first value
  3. second value

swap한 후 두 값을 별도의 줄에 출력합니다. double의 경우 소수점 이하 2자리를 사용합니다.

입력이 i, 5, 10일 때의 예시 출력:

10
5

입력이 d, 3.14, 2.71일 때의 예시 출력:

2.71
3.14

입력이 i, -7, 42일 때의 예시 출력:

42
-7

입력이 d, 99.99, 0.01일 때의 예시 출력:

0.01
99.99

이 접근 방식의 장점은 generic_swap function이 어떤 type을 swap하고 있는지 전혀 알 필요가 없다는 것입니다. 단지 bytes를 이동할 뿐입니다. 동일한 function이 정수, double, struct 또는 다른 어떤 data type에도 작동합니다. memcpy를 사용하려면 <string.h>를, size_t를 사용하려면 <stddef.h> 또는 <stdlib.h>를 include해야 합니다.

직접 해보기

#include <stdio.h>
#include "swap.h"

int main() {
    char type;
    scanf("%c", &type);
    
    if (type == 'i') {
        int a, b;
        scanf("%d", &a);
        scanf("%d", &b);
        
        // TODO: generic_swap을 호출하여 a와 b를 교환하세요
        // Hint: &a, &b, 그리고 sizeof(int)를 사용하세요
        
        printf("%d\n", a);
        printf("%d\n", b);
    } else if (type == 'd') {
        double a, b;
        scanf("%lf", &a);
        scanf("%lf", &b);
        
        // TODO: generic_swap을 호출하여 a와 b를 교환하세요
        // Hint: &a, &b, 그리고 sizeof(double)를 사용하세요
        
        printf("%.2f\n", a);
        printf("%.2f\n", b);
    }
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 C 컴파일러