2 type
초의 매개 변수 를 허용하려는 함수를 작성 중입니다.
- A
string
(char *) structure
n 개의 요소가있는 A.
그리고 이것을 달성하기 위해 void *
매개 변수 유형 으로 간단한 것을 사용할 생각입니다 . 그러나 매개 변수가 하나의 유형인지 다른 유형인지 안전하게 확인하는 방법을 모르겠습니다.
func_str
및 func_struct
및 컴파일 타임에 유형 검사를 얻을.
2 type
초의 매개 변수 를 허용하려는 함수를 작성 중입니다.
string
(char *)structure
n 개의 요소가있는 A.그리고 이것을 달성하기 위해 void *
매개 변수 유형 으로 간단한 것을 사용할 생각입니다 . 그러나 매개 변수가 하나의 유형인지 다른 유형인지 안전하게 확인하는 방법을 모르겠습니다.
func_str
및 func_struct
및 컴파일 타임에 유형 검사를 얻을.
답변:
번역 void*
은
"친애하는 컴파일러, 이것은 포인터이며, 이에 대한 추가 정보는 없습니다."입니다.
일반적으로 컴파일러는 이전에 얻은 정보로 여전히 기억하고 잊어 버렸을 수 있기 때문에 프로그래머보다 더 잘 알고 있습니다.
그러나이 특별한 경우에, 당신은 더 잘 알거나 더 잘 알아야합니다. void*
정보 의 모든 경우에 다른 방법으로 이용할 수 있지만 "알아야하는"프로그래머 만 사용할 수 있습니다. 프로그래머는 정보를 컴파일러에 제공해야합니다. 또는 실행중인 프로그램에 더 좋습니다. 한 가지 장점 void*
은 정보가 런타임 중에 변경 될 수 있기 때문 입니다.
일반적으로 이는 추가 매개 변수를 통해 정보를 함수에, 때로는 컨텍스트를 통해 (예 : "알아야하는"프로그램) 제공합니다 (예 : 가능한 각 유형마다 별도의 함수가 있으며, 함수는 형식을 의미합니다).
결국 void*
에는 정보 유형이 포함되지 않습니다.
많은 프로그래머들이 이것을 "유형 정보를 알 필요가 없습니다"라고 오해합니다.
그러나 그 반대의 경우에, 사용 하면 타입 정보를 추적하고 적절하게 프로그램 / 컴파일러에 제공하는 프로그래머의 책임 이 void*
증가 합니다.
void*
함수 로 뛰어 들어서 잘못된 유형으로 캐스팅 한 다음 데이터를 참조 해제하면 모든 방식의 정의되지 않은 동작이 호출됩니다.
void*
일반적인 프로그래밍에서는 더 이상 사용되지 않지만 요즘에는 사용해야 할 상황이 많지 않습니다. 존재하지 않는 유형의 안전으로 이어지기 때문에 위험합니다. 그리고 언급했듯이 유형 정보도 잃어 버렸습니다. 즉, enum
과 함께 번거로운 부분 을 드래그해야 합니다 void*
.
대신 _Generic
컴파일 타임에 유형을 확인하고 유형 안전을 추가 할 수있는 C11 을 사용해야합니다 . 예:
#include <stdio.h>
typedef struct
{
int n;
} s_t; // some struct
void func_str (const char* str)
{
printf("Doing string stuff: %s\n", str);
}
void func_s (const s_t* s)
{
printf("Doing struct stuff: %d\n", s->n);
}
#define func(x) _Generic((x), \
char*: func_str, const char*: func_str, \
s_t*: func_s, const s_t*: func_s)(x) \
int main()
{
char str[] = "I'm a string";
s_t s = { .n = 123 };
func(str);
func(&s);
}
const
지원하려는 모든 유형의 정규화 된 버전 을 제공해야합니다 .
호출자가 잘못된 유형을 전달할 때 더 나은 컴파일러 오류를 원하면 정적 어설 션을 추가 할 수 있습니다.
#define type_check(x) _Static_assert(_Generic((x), \
char*: 1, const char*: 1, \
s_t*: 1, const s_t*: 1, \
default: 0), #x": incorrect type.")
#define func(x) do{ type_check(x); _Generic((x), \
char*: func_str, const char*: func_str, \
s_t*: func_s, const s_t*: func_s)(x); }while(0)
같은 것을 시도 int x; func(x);
하면 컴파일러 메시지가 나타납니다 "x: incorrect type"
.
void*
포인트를 나타내는 두 번째 매개 변수를 추가해야 합니다.