【问题标题】:Declaring void pointers to push type handling downstream声明 void 指针以向下游推送类型处理
【发布时间】:2019-10-01 04:05:15
【问题描述】:

是否经常做以下事情:

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

代替:

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

我问这个的原因是能够调用一个可以接受多种类型的函数。例如,各种元素的 concat 可以在 javascript 中使用。在某种程度上,使用(void *) 似乎只是表示“任何类型”的一种简单方式。

【问题讨论】:

  • 不,它会阻止类型检查,最好避免使用,并且不能用于避免应用严格别名规则。它是有效的,只是不聪明。
  • 实际上,它正在创建指向内存单元 0x2 的指针,而不是第二行中的常量 2

标签: c pointers void


【解决方案1】:

不,因为您不能取消引用 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);

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

【讨论】:

  • 能否举个例子说明如何调用该结构来声明一个项目?
  • Aldo,有 vaarg 可以处理这样的情况,但是你需要在调用时以某种方式传递类型(如 printf)。我敢打赌,你可以在这里使用宏变得聪明,让调用变得花哨......
【解决方案2】:

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

但是,在某些情况下,您可能希望使用 '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") ;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    相关资源
    最近更新 更多