C - 动态转换void结构指针

时间:2016-07-07 22:52:43

标签: c struct void-pointers

我想根据变量的值将指针强制转换为两个结构中的一个。我正在尝试这个但它不起作用 -

struct typeA
{
     int a;
     int x;
}
struct typeB
{
     int b;
     int a;
     int x;
     int z;
}


int band=1;
void *ptr;

if(band == 1)
            ptr = (struct typeA *)malloc(sizeof(struct typeA));
else if(band == 2)
            ptr = (struct typeB *)malloc(sizeof(struct typeB));

printf("A:%d",ptr->a);//error: structure type required instead of void

最好的方法是什么?

编辑:添加结构定义和错误(在代码注释中)以使其更有意义。

5 个答案:

答案 0 :(得分:2)

正如其他人所建议的那样,您可能需要更改设计,因为它有一些缺陷。

但是,要解决编译错误,您可以执行以下操作:

 printf("A:%d",(band == 1) ? ((struct typeA *)ptr)->a : ((struct typeB *)ptr)->a);

您收到错误是因为您在a时尝试从void *访问成员ptr->a

您需要明确地说明ptr指向struct typeAstruct typeB

答案 1 :(得分:1)

如果您不需要知道自己的结构类型,请使用

if(band == 1)
        ptr = malloc(sizeof(struct typeA));
else if(band == 2)
        ptr = malloc(sizeof(struct typeB));

malloc的返回类型已为void *

但是,这是一个code smell ---您真的在创建结构后不需要知道结构的大小或类型吗?我会重新考虑你的设计。

修改根据您发布的其他代码,我强烈推荐一种新方法。例如,typeAtypeB中的字段的顺序不同,因此无论ptr->a的类型如何,ptr都无法引用这两个字段。如果您遇到普通C,请考虑一个struct ax,以及指向bz的单独结构的可选指针。或者,只需使用typeB即可,然后移除typeA

答案 2 :(得分:1)

你永远不应该投射malloc的结果,因为这样做会掩盖其他问题。它也会在这里引起警告,因为类型不匹配。

摆脱演员阵容,你不应该收到任何警告。

编辑:

错误是因为您试图取消引用void *,这是非法的。

不使用一个变量,而是使用两个(每种类型之一)并将另一个设置为NULL。或者,如果您知道void *指向的数据类型,则可以将其转换为正确的类型,然后取消引用它。

答案 3 :(得分:1)

这里的演员阵容什么都不买,因为每个演员阵容的结果会立即转换为ptr的类型。无论哪种方式,指向malloc ed对象的指针最终都存储在ptr中,而ptr只有一个与malloc返回的完全匹配的静态类型。唯一不同的行为是malloc - ed区域的大小。

你的逻辑可以简化为一行:

void *ptr = malloc(band == 1 ? sizeof (struct typeA) : sizeof (struct typeB));

需要更多的上下文来确定这是否是一个关于周围代码的好方法,或者是否更加严格的“类OOP”会更好,或者是否在两个单独的代码段之间进行简单切换在不同的结构上。

实际对象无法在没有额外强制转换的情况下以typeAtypeB的形式进行访问,因此可以想象许多丑陋的代码如下所示,例如

if (band == 1)
   do_this_A_version((struct typeA *) ptr)->foo, x);
else
   do_this_B_version((struct typeB *) ptr)->bar, y);

有很好的方法可以避免这类问题,超出了这个问题的范围。

答案 4 :(得分:1)

[编辑] 编辑OP后更新了代码段。

这是第二次猜测实际的问题,但也许以下是什么 你在追求。

java.lang.RuntimeException: com.sun.tools.javac.code.Symbol$CompletionFailure: class file for org.openxmlformats.schemas.officeDocument.x2006.docPropsVTypes.CTArray not found