在plain c中,我有一个情况,我想允许一个函数接受多种类型的指针。为了说明我的情况,这里可能有一个用例:
void myfunction([int* or char*] value) {
*value = 0xdd; // safe since value is at least as big as a char*
}
#define MAGIC 0xabcdef0
typedef struct {
int magic;
char* content;
} MyStruct;
void myfunction([int* or MyStruct*] value) {
if (*value != MAGIC) {
printf("Got an intn");
} else {
printf("Got a MyStructn");
}
}
// example:
int input1 = 0;
MyStruct input2 = { MAGIC, "hello world" };
myfunction(input1); // "Got an int"
myfunction(input2); // "Got a MyStruct"
这两种情况都可以通过void*
参数类型来实现,但这实际上允许传入任何类型的指针而不会出现编译错误。是否有一种方法来限制函数只接受指针类型的特定子集?
如果您可以使用C11中的新功能,那么_Generic
关键字可以解决您的问题:
void myfunction(void *value) {
// ...
}
#define myfunction(x) myfunction(
_Generic((x), char *: (x), int *: (x)) )
正如Houman指出的那样,您可以使用联合来完成这项工作,但是,您仍然存在必须识别在联合类型中设置的类型的问题。您可以使用enum来标识函数内部的类型来解决这个问题。
union myUnion {
int* intPointer,
MyStruct* myStructPointer
};
enum typeEnum {
INT,
MYSTRUCT
};
void myfunction(union myUnion union, enum typeEnum type) {
if (type == INT)
// you got an integer
else if (type == MYSTRUCT)
// you got a struct
// You can add future additions here
}
你可以这样做:
void myfunction(void *s)
{
if ( *(int *)s == MAGIC )
{
MyStruct *p = s;
printf("%sn", p->content);
}
}
然而,这种设计使编写编译器无法捕获的错误代码变得容易,因此我建议提出一个稍微不同的设计(例如标记联合)。
不,用void*
再cast。
可以认为我可以使用void*
,然后检查函数内部的类型转换,如果不是预期的类型,则引发错误,但是不,您也不能这样做,因为void*
丢失了所有类型信息。
该死,我在洗澡前写东西。我无法抗拒!BRB:)——好吧,原来是R…来自未来的答案是正确的!)