void*
เป็นประเภทที่เลิกใช้สำหรับการเขียนโปรแกรมทั่วไปมีหลายสถานการณ์ที่คุณควรใช้ในปัจจุบัน พวกมันมีอันตรายเพราะมันนำไปสู่ความปลอดภัยประเภทที่ไม่มีอยู่จริง และเป็นคุณสังเกตเห็นว่าคุณยังสูญเสียข้อมูลประเภทที่มีความหมายที่คุณจะต้องลากไปรอบ ๆ ยุ่งยากบางส่วนพร้อมกับenum
void*
คุณควรใช้ C11 _Generic
ซึ่งสามารถตรวจสอบประเภทของเวลาคอมไพล์และเพิ่มความปลอดภัยของประเภท ตัวอย่าง:
#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*
ชี้ไป