void*
là loại không dùng cho lập trình chung, hiện tại không có nhiều tình huống bạn nên sử dụng chúng. Chúng nguy hiểm vì chúng dẫn đến loại an toàn không tồn tại. Và như bạn đã lưu ý, bạn cũng mất thông tin loại, nghĩa là bạn phải kéo theo một số thứ cồng kềnh enum
cùng với void*
.
Thay vào đó, bạn nên sử dụng C11 _Generic
có thể kiểm tra các loại tại thời gian biên dịch và thêm an toàn loại. Thí dụ:
#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);
}
Hãy nhớ cung cấp const
các phiên bản đủ điều kiện ( ) của tất cả các loại bạn muốn hỗ trợ.
Nếu bạn muốn lỗi trình biên dịch tốt hơn khi người gọi vượt qua loại sai, bạn có thể thêm một xác nhận tĩnh:
#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)
Nếu bạn thử một cái gì đó như int x; func(x);
bạn sẽ nhận được thông báo trình biên dịch "x: incorrect type"
.
void*
điểm đó là gì .