C语言 你能允许几种类型的指针之一作为参数而不使用void*吗?



在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…来自未来的答案是正确的!)

最新更新