제네릭 스왑
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.14void*와 size_t를 사용하는 이 패턴은 C의 표준 라이브러리가 qsort 및 bsearch와 같은 제네릭 함수를 구현하는 방식입니다.
챌린지
쉬움void* 포인터와 memcpy의 강력한 기능을 사용하여, 자료형과 관계없이 두 변수의 값을 교환할 수 있는 범용 swap 유틸리티를 만들어 봅시다.
코드를 세 개의 파일로 구성합니다:
swap.h: 두 개의void*포인터와 교환할 데이터의 크기를 나타내는size_t매개변수를 받는generic_swapfunction을 Declare합니다. include guard도 잊지 마세요!swap.c:generic_swapfunction을 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_swapfunction을 사용하여 swap한 뒤, swap 후 두 값을 모두 출력합니다.
프로그램은 세 개의 입력을 받습니다:
- type indicator: 정수는
i, double은d - first value
- 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;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 C 컴파일러