3

好的,我正在尝试这样做,但它不起作用,因为我没有取消引用指针......有没有办法在不为类型创建 switch 语句的情况下做到这一点?

typedef struct
{
    char *ascii_fmtstr;
    int len;
    int (*deserializer)(void *in, const char *ascii);
    int (*serializer)(const void *in, char *ascii);
} FORMAT;

const FORMAT formats[]=
{
    {"%d\n",    2/2}        //Int
    ,{"%s\n",   STRSIZE/2}  //String
    ,{"%.4f\n", 4/2}        //Float
    ,{"%lld",   4/2}        //Long-Long
    ,{"%s\n",   STRSIZE/2}  //Time
};

typedef struct {
    int fmtindex;
    void * vp;
} JUNK;

float f = 5.0f;
int i=1;
char foo[]="bar";

JUNK j[] = {
     {2, &f}
     ,{0, &i}
     ,{1, foo}};

void dump(void)
{
    int i;
    for(i=0;i<2;i++)
        printf(formats[j[i].fmtindex].ascii_fmtstr, j[i].vp);

}
4

5 回答 5

2

您可以使用类似的方式打印指针本身,%p但是,如果您想打印它指向的内容您需要告诉它它是什么:

printf ("%d", *((int*)myVoidPtr));

您不能void *仅仅因为编译器不知道它指向什么而取消引用 a 。

于 2013-04-26T05:38:21.133 回答
2

看来您正在使用void *便宜的union. 这是一个非常糟糕的主意。我认为您会发现unions 与enums 和switches 结合使用会使这看起来更加整洁,在 C 中。您会在 ... 中找到switch#ifdef SWITCH开关#else版本在#else...#endif中。

#include <stdio.h>

struct object {
    enum type {
        d=0,
        s=1,
        f=2,
        lld=3,
        time=4
    } type;

    union instance {
        int d;
        char *s;
        float f;
        long long lld;
        char *time;
    } instance;
};

#ifdef SWITCH
void print_object(struct object *o) {
    switch (o->type) {
        case d: printf("%d", o->instance.d); break;
        case s: printf("%s", o->instance.s); break;
        case f: printf("%f", o->instance.f); break;
        case lld: printf("%lld", o->instance.lld); break;
        case time: printf("%s", o->instance.time); break;
    };
}
#else
void print_d(struct object *o);
void print_s(struct object *o);
void print_f(struct object *o);
void print_lld(struct object *o);
void print_time(struct object *o);

void print_object(struct object *o) {
    void (*print_functions[])(struct object *) = {
         [d] = print_d,
         [s] = print_s,
         [f] = print_f,
         [lld] = print_lld,
         [time] = print_time
    };

    print_functions[o->type](o);
}

void print_d(struct object *o) { printf("%d", o->instance.d); }
void print_s(struct object *o) { printf("%s", o->instance.s); }
void print_f(struct object *o) { printf("%f", o->instance.f); }
void print_lld(struct object *o) { printf("%lld", o->instance.lld); }
void print_time(struct object *o) { printf("%s", o->instance.time); }
#endif

int main(void) {
    struct object o = { .type = d,                /* type: int */
                        .instance = { .d = 42 }   /* value: 42 */ };

    print_object(&o);
    return 0;
}
于 2013-04-26T06:33:11.617 回答
1

这样想:Any指针只指向一个内存位置type。但是指针的 确定how many之后要解释/考虑的字节。如果是char*(取决于系统)解释 1 个字节,如果是int*4 个字节解释,等等。但是一个void*有。因此,由于这个简单的原因,no type您不能取消引用 C 中的指针。但是您可以使用格式说明符void打印出它指向的地址并将该指针作为参数传递。%pprintf()void

printf("The address pointed by void pointer is %p",void_ptr); //Correct

printf("The address pointed by void pointer is %p",(void*)int_ptr);//Correct

假设int_ptr是一个整数指针,比如说,并且void_ptr是一个空指针。

printf("Value at address pointed by void pointer is %d",*void_ptr);// Wrong

printf("Value at address pointed by void pointer is %d",*(void*)int_ptr);//Wrong
于 2013-04-26T05:51:36.183 回答
0

目前尚不清楚您的真正目标是什么。是的,有一些方法可以根据数据类型打印。基本上这个想法是创建自己的打印功能。

但仅提供指针是不够的。在任何情况下,您都需要提供指针及其类型。

假设我们有一个函数myprint

myprint("%m %m %m %i", TYPE_INT, &i, TYPE_FLOAT, &f, TYPE_STRING, foo, 10);

将是一个可能的电话。myprint是一个 varargs 函数,它需要重建格式字符串和参数,然后可以调用 real printf

如果仅使用堆变量,则可以通过一些技巧将变量的类型与数据一起存储(提示:检查如何malloc存储块大小)。这将使额外的论点变得多余。

还有其他解决方案,但是如果不了解您的真正目标和确切条件,就不可能提出好的建议。

于 2013-04-26T05:56:05.707 回答
0

我认为 theprintf及其朋友(fprintf 等)只能取消引用char*,这将被解释为 c 字符串。

实际上你可以自己编写这样的函数,因为你会告诉你的函数如何取消引用void*格式标志。

您还可以将formats一个指向所需解引用函数的指针作为第三个值添加到该函数中,该函数将作为参数 avoid*并返回值而不是指针。因此,您需要为格式中使用的每种类型编写一个函数,并将每个函数正确分配给每种格式。

于 2013-04-26T06:03:38.713 回答