声明 void 指针以将类型处理推送到下游

Declaring void pointers to push type handling downstream

像下面这样的事情是否常见:

void *x = (void *) "one";
void *y = (void *) 2;
void *z = (void *) NULL;

而不是:

char * x = "one";
int y = 2;

我问这个的原因是能够调用一个可以接受多种类型的函数。例如,在 javascript 中可以使用各种元素的连接,例如 javascript。似乎在某种程度上使用 (void *) 只是表示 "any type".

的一种简单方法

不,因为您不能取消引用 void 指针:您必须知道存储的是什么类型,这会使这个想法变得毫无用处。

您可能正在寻找的是 variant type

enum type {
    CHAR, INT, DOUBLE, STR
};

typedef struct {
    union {
        char   c;
        int    i;
        double d;
        char   *str;
    };
    enum type t;
} variant;

void displayGenericObjec(variant v)
{
    switch (v.t) {
        case CHAR:
            putchar(v.c);
            break;
        case INT:
            printf("%d", v.i);
            break;
        case DOUBLE:
            printf("%f", v.d);
            break;
        case STR:
            printf("%s", v.str);
            break;
    }
}

variant x;
x.t = INT;
x.i = 42;
displayGenericObject(x);

这不是一个非常实用的解决方案,但它适用于只需要几种类型的普通代码。

通常,编写带有任何参数的函数并不是一个好主意。如评论中所述,您失去了编译器提供的类型检查。

但是,在某些情况下您可能需要考虑使用 'void *',这些情况(通常)被认为是可以接受的:(1) 可变参数函数和 (2) 回调。重要的是要强调,如果可能,最好考虑替代实施。

varargs 函数是像 'printf'、'scanf' 等函数,其中函数可以接受可变数量的参数,可能是不同的类型,并且通常会使用来自正确解码其余参数的第一个参数。

回调是其他示例,其中代码有时必须指定将在事件发生时调用的函数。许多框架将要求回调匹配预定义的 "typedef",代码稍后会将参数转换为实际类型。例如,'qsort' 原型需要一个 'compar' 函数,该函数通常定义为采用 'void *',其中实际函数会将参数转换为实际类型。

void qsort(void *base, size_t nmemb, size_t size,
                  int (*compar)(const void *, const void *));

根据历史记录,"C" 的初始版本(有时称为 "K&R C")确实允许在没有形式参数列表的情况下定义函数。实践经验证明,这样做是有风险的、无益的。在那些日子里,您可以在头文件中编写函数,例如:

/* in file.h */
int foo() ;
/* in file.c */
int foo(a)
   int a ;
{
}
/* in prog.c */
{
    a(5,4,"x") ;
}