【问题标题】:How to typecast void pointer based on condition?如何根据条件对 void 指针进行类型转换?
【发布时间】:2015-05-13 15:59:18
【问题描述】:

为了解释更多,我有两个结构 - 'first' 和 'second' 具有公共变量 'jack' 和 'jill'。我想通过基于 if-else 条件的指针打印插孔。 我明白在打印时我必须对 void 指针进行类型转换。但是指针指向结构 a 还是 b 取决于运行时间。 这是一个基本的 C 代码。如何克服?

代码

#include <stdio.h>

int main(void)
{

typedef struct one
{
    int jack;
    float jill;
}a;
typedef struct two
{
    int jack;
    float jill;
    char something;
    int something1;
}b;
a first;
b second;

void *z;

if(1)
{
    a* z;
    z = &first;
    printf("First one");
}
else
{
    b* z;
    z = &second;
    printf("Second one");
}

printf("%d\n", z->jack);


    return 0;
}

错误

prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union

【问题讨论】:

  • 你想做什么? printf("b is %F", x) 想要 x 的浮点参数(因为 %f 是浮点格式说明符)。不是void。由于与printf("Value is %d", *a) 相同的原因,您将收到类似的错误。目前还不清楚你想要什么。无论哪种情况,您都想将值打印为浮点数吗?
  • 也不确定你想做什么,但如果你知道结果类型,你可以像这样int intVal = *((int *) a);
  • 抱歉,潜伏者和 fbo3264 的信息模糊/错误。已更新 Q。

标签: c pointers if-statement casting void


【解决方案1】:

您收到编译器警告,因为编译器不理解 z-&gt;jack,因为 zvoid *(请注意声明 a* zb* zifelse 块)。

要克服这个问题,您可以使用函数printJack,如下所示:

#include <stdio.h>

typedef struct one
{
    int jack;
    float jill;
}a;

typedef struct two
{
    int jack;
    float jill;
    char something;
    int something1;
}b;


void printJack(void *pStruct, int type)
{
    switch (type)
    {
        case 1:
            printf("jack: %d\n", ((a *)pStruct)->jack);
            break;

        default:
            printf("jack: %d\n", ((b *)pStruct)->jack);
            break;
    }
}


/*
**    main
*/
int main(void)
{
    a first;
    b second;
    void *z;

    first.jack = 5;
    second.jack = 4892;

    printJack(&first, 1);
    printJack(&second, 0);

    z = &first;
    printJack(z, 1);

    return (0);
}

我经常编写这样的代码并且遇到了很多麻烦。不是在实现的时候,因为你知道你在那一刻输入了什么,但是如果你需要扩展你的代码,让我们说几年后。您会错过从void * 转换为a *b * 的一些地方,并且您将花费大量时间调试正在发生的事情...

现在我用以下方式写这样的东西:

#include <stdio.h>


typedef struct header
{
    int jack;
    float jill;
} h;

typedef struct one
{
    struct header header;

    /* what ever you like */
}a;

typedef struct two
{
    struct header header;

    char something;
    int something1;

    /* and even more... */
}b;


void printJack(void *pStruct)
{
    printf("jack: %d\n", ((struct header *)pStruct)->jack);
}


/*
**    main
*/
int main(void)
{
    a first;
    b second;
    void *z;

    first.header.jack = 5;
    second.header.jack = 4892;

    printJack(&first);
    printJack(&second);

    v = &first;
    printJack(v);

    return (0);
}

正如您所注意到的,我声明了一个新的struct header,它涵盖了struct onestruct two 的公共部分。不是将void * 转换为a *b *,而是将“普通”转换为struct header *(或h *)。

通过这样做,您可以轻松地扩展结构的“公共属性”,或者您可以使用此标头和函数printJack 实现更多结构,仍然可以工作。此外,不再需要属性type,更容易调用printJack。您甚至可以更改 jack 的类型,而无需在代码中的各个位置进行更改。

但请记住,struct header 必须是您使用此机制的结构的第一个元素。否则你会得到一些惊喜,因为你使用的内存不包含struct header的数据...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-14
    • 2021-09-20
    • 1970-01-01
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多