您可以允许几种类型的指针中的一种作为不带 void* 的参数吗?
Can you allow one of a few types of pointers as an argument without void*?
简而言之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 int\n");
} else {
printf("Got a MyStruct\n");
}
}
// example:
int input1 = 0;
MyStruct input2 = { MAGIC, "hello world" };
myfunction(input1); // "Got an int"
myfunction(input2); // "Got a MyStruct"
这两种情况都可以使用 void*
参数类型来实现,但这实际上允许传入任何类型的指针而不会出现编译错误。有没有办法限制函数只接受指针类型的特定子集?
不行,先用void*
再投
有人可能认为我可以使用 void*
然后检查函数内部的转换,如果不是预期的类型,则引发错误,但不,你也不能这样做,因为 void*
loses all its type information.
该死的,我在洗澡前才写。我无法抗拒! BRB :) -- 好的,事实证明 R.. 来自 future 的答案是正确的! ;)
你可以这样做:
void myfunction(void *s)
{
if ( *(int *)s == MAGIC )
{
MyStruct *p = s;
printf("%s\n", p->content);
}
}
然而,这种设计使得编写编译器不会为您捕获的错误代码变得容易,因此我建议提出一个稍微不同的设计(例如标记联合)。
正如 Houman 指出的那样,您可以使用联合来完成这项工作,但是,您仍然有一个问题,即您必须识别在联合类型中设置的类型。您可以使用枚举来识别函数内的类型来解决这个问题。
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
}
如果您可以使用 C11 中的新功能,_Generic
关键字可以解决您的问题:
void myfunction(void *value) {
// ...
}
#define myfunction(x) myfunction( \
_Generic((x), char *: (x), int *: (x)) )
简而言之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 int\n");
} else {
printf("Got a MyStruct\n");
}
}
// example:
int input1 = 0;
MyStruct input2 = { MAGIC, "hello world" };
myfunction(input1); // "Got an int"
myfunction(input2); // "Got a MyStruct"
这两种情况都可以使用 void*
参数类型来实现,但这实际上允许传入任何类型的指针而不会出现编译错误。有没有办法限制函数只接受指针类型的特定子集?
不行,先用void*
再投
有人可能认为我可以使用 void*
然后检查函数内部的转换,如果不是预期的类型,则引发错误,但不,你也不能这样做,因为 void*
loses all its type information.
该死的,我在洗澡前才写。我无法抗拒! BRB :) -- 好的,事实证明 R.. 来自 future 的答案是正确的! ;)
你可以这样做:
void myfunction(void *s)
{
if ( *(int *)s == MAGIC )
{
MyStruct *p = s;
printf("%s\n", p->content);
}
}
然而,这种设计使得编写编译器不会为您捕获的错误代码变得容易,因此我建议提出一个稍微不同的设计(例如标记联合)。
正如 Houman 指出的那样,您可以使用联合来完成这项工作,但是,您仍然有一个问题,即您必须识别在联合类型中设置的类型。您可以使用枚举来识别函数内的类型来解决这个问题。
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
}
如果您可以使用 C11 中的新功能,_Generic
关键字可以解决您的问题:
void myfunction(void *value) {
// ...
}
#define myfunction(x) myfunction( \
_Generic((x), char *: (x), int *: (x)) )