Void 포인터 복습
Coddy C 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 49번째.
void*는 "무언가를 가리키는 포인터이지만, 그것이 무엇인지는 알려주지 않겠다"는 C 언어의 방식입니다. 이것은 int, float, 구조체 또는 그 외 어떤 데이터 타입의 주소도 가질 수 있습니다. 이로 인해 C에서 제네릭(generic) 코드를 작성하기 위한 기초가 됩니다.
주의할 점은 void*를 직접 역참조(dereference)할 수 없다는 것입니다. 컴파일러는 몇 바이트를 읽어야 할지, 혹은 그것을 어떻게 해석해야 할지 알지 못합니다. 데이터를 사용하려면, 올바른 타입으로 다시 형변환(cast)해야 합니다:
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}이러한 유연성에는 책임이 따릅니다. 잘못된 타입으로 형변환하더라도 컴파일러는 이를 막지 않지만, 프로그램은 쓰레기 값을 생성하거나 충돌(crash)이 발생할 것입니다. 그렇기 때문에 제네릭 함수는 종종 void*를 타입 표시자(enum이나 플래그 등)와 함께 사용하여 함수가 데이터를 올바르게 해석하는 방법을 알 수 있도록 합니다.
이어지는 레슨에서는 void*를 사용하여 모든 타입의 데이터를 저장할 수 있는 컨테이너를 구축하고, 진정으로 재사용 가능한 데이터 구조를 만들어 볼 것입니다.
챌린지
쉬움데이터에 대한 void* 포인터와 int 타입 플래그라는 두 개의 매개변수를 받는 print_value 함수를 작성하세요. 이 함수는 타입 플래그에 따라 데이터를 해석하고 출력해야 합니다:
- 타입 플래그가
0인 경우, 포인터를int*로 캐스팅하고 정수 값을 출력합니다. - 타입 플래그가
1인 경우, 포인터를float*로 캐스팅하고 소수점 둘째 자리까지 부동 소수점 값을 출력합니다.
프로그램은 두 개의 입력을 받습니다:
- 타입 플래그 (정수의 경우
0, 부동 소수점의 경우1) - 숫자 값
타입 플래그에 따라 값을 적절한 변수 타입에 저장한 다음, 해당 변수에 대한 포인터와 타입 플래그를 사용하여 print_value를 호출하세요.
입력이 0과 42일 때의 예시 출력:
42입력이 1과 3.14일 때의 예시 출력:
3.14입력이 0과 -17일 때의 예시 출력:
-17입력이 1과 99.5일 때의 예시 출력:
99.50치트 시트
void*는 모든 데이터 타입의 주소를 저장할 수 있는 범용 포인터입니다. 이는 C 언어에서 범용 코드를 작성할 수 있는 유연성을 제공합니다.
void*를 직접 역참조할 수는 없습니다. 먼저 올바른 타입으로 캐스팅해야 합니다:
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}범용 함수는 데이터를 올바르게 해석하는 방법을 알기 위해 종종 void*를 타입 표시자(열거형이나 플래그 등)와 함께 사용합니다. 잘못된 타입으로 캐스팅하면 정의되지 않은 동작이나 프로그램 충돌이 발생할 수 있습니다.
직접 해보기
#include <stdio.h>
// TODO: 여기에 print_value 함수를 작성하세요
int main() {
int type_flag;
scanf("%d", &type_flag);
if (type_flag == 0) {
int int_value;
scanf("%d", &int_value);
// TODO: int_value의 포인터와 타입 플래그를 사용하여 print_value를 호출하세요
} else if (type_flag == 1) {
float float_value;
scanf("%f", &float_value);
// TODO: float_value의 포인터와 타입 플래그를 사용하여 print_value를 호출하세요
}
return 0;
}이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.