的翻译void*是
“亲爱的编译器,这是一个指针,对此您没有其他信息。”。
通常,编译器比您(程序员)更了解您,因为他获取的信息更早并且仍然记得并且您可能已经忘记了。
但是在这种特殊情况下,您会了解更多或需要了解更多。在所有情况下,void*信息都是可用的,但仅适用于“偶然知道”的程序员。为此,程序员必须将信息提供给编译器-或者更好地提供给正在运行的程序,因为一个优点void*是该信息可以在运行时更改。
通常,这是通过通过附加的参数给函数(有时是通过上下文)将信息提供给程序来完成的,例如,程序“碰巧知道”(例如,对于每种可能的类型,都有一个单独的函数,无论调用哪个函数都暗含该类型)。
所以最后void*不包含类型信息。
许多程序员误解为“我不需要知道类型信息”。
但是事实恰恰相反,使用void* 增加程序员的责任,以跟踪类型信息并将其适当地提供给程序/编译器。
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);
}
Run Code Online (Sandbox Code Playgroud)
请记住提供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)
Run Code Online (Sandbox Code Playgroud)
如果您尝试类似的操作,int x; func(x);您将收到编译器消息"x: incorrect type"。
| 归档时间: |
|
| 查看次数: |
105 次 |
| 最近记录: |