void*
agak usang untuk pemrograman generik, tidak ada banyak situasi di mana Anda harus menggunakannya saat ini. Mereka berbahaya karena menyebabkan keamanan tipe yang tidak ada. Dan seperti yang Anda catat, Anda juga kehilangan informasi jenis, yang berarti Anda harus menyeret beberapa rumit enum
bersama dengan void*
.
Sebagai gantinya Anda harus menggunakan C11 _Generic
yang dapat memeriksa jenis pada waktu kompilasi dan menambahkan keamanan jenis. Contoh:
#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);
}
Ingatlah untuk menyediakan const
versi yang memenuhi syarat ( ) dari semua jenis yang ingin Anda dukung.
Jika Anda ingin kesalahan kompiler yang lebih baik ketika pemanggil melewati tipe yang salah, Anda bisa menambahkan pernyataan statis:
#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)
Jika Anda mencoba sesuatu seperti int x; func(x);
Anda akan mendapatkan pesan kompiler "x: incorrect type"
.
void*
poin.