C-动态地将void指针转换为结构
我想根据变量的值将指针强制转换为两种结构之一。我正在尝试,但它不起作用-C-动态地将void指针转换为结构,c,struct,void-pointers,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)); els
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
最好的方法是什么
编辑:添加结构定义和错误(在代码注释中)以使其更有意义。如果您不需要知道所使用的结构类型,请使用
if(band == 1)
ptr = malloc(sizeof(struct typeA));
else if(band == 2)
ptr = malloc(sizeof(struct typeB));
的返回类型已经是void*
然而,这是一个---你真的不需要在你创建它之后知道它的大小或类型吗?我会重新考虑一下你的设计
编辑根据您发布的其他代码,我强烈推荐一种新方法。例如,
typeA
和typeB
中的字段顺序不同,因此无论ptr
的类型如何,ptr->a
都无法引用这两个字段。如果您使用了纯C,请考虑一个<代码>结构> <代码>,它有<代码> < <代码> >代码> x>代码>,以及一个可选的指针,指向一个单独的结构,它具有“代码> b<代码>和<代码> z <代码>。或者,只需对所有内容使用typeB
,然后删除typeA
您不应该强制转换malloc的结果,因为这样做可能会掩盖其他问题。因为类型不匹配,所以在这里也会引起警告
摆脱强制类型转换,您将不会收到任何警告
编辑:
该错误是因为您试图取消对无效*
的引用,这是非法的
使用两个变量(每种类型一个)并将另一个设置为NULL,而不是使用一个变量。或者,如果您知道
void*
所指向的数据类型,您可以将其转换为正确的类型,然后取消引用。这里的转换不会给您带来任何好处,因为每次转换的结果都会立即转换为ptr
的类型。无论哪种方式,指向malloc
-ed对象的指针最终存储在ptr
中,并且ptr
有一个与malloc
返回的内容完全匹配的静态类型。唯一不同的行为是malloc
-ed区域的大小
您的逻辑可以简化为一行:
void *ptr = malloc(band == 1 ? sizeof (struct typeA) : sizeof (struct typeB));
对于周围的代码,这是否是一种很好的方法,或者更严格的“面向对象的”方法是否更好,或者在两段独立的代码之间进行简单的切换是否在独立的结构上工作,都需要更多的上下文
如果没有额外的强制转换,实际对象不能作为typeA
或typeB
访问,因此可以想象会出现很多丑陋的代码,例如
if (band == 1)
do_this_A_version((struct typeA *) ptr)->foo, x);
else
do_this_B_version((struct typeB *) ptr)->bar, y);
有一些很好的方法可以避免这类问题,超出了这个问题的范围。[p>[EDIT]代码段在OP编辑后更新
这是对实际问题的二次猜测,但也许下面是什么
你在找我
struct typeA
{
int a;
int x;
};
struct typeB
{
int b;
int a;
int x;
int z;
};
union { struct typeA *A; struct typeB *B; } ptr;
if(band == 1)
ptr.A = malloc(sizeof(struct typeA));
else if(band == 2)
ptr.B = malloc(sizeof(struct typeB));
/* ... later on ... */
if(band == 1)
printf("A::a = %d", ptr.A->a); /* use ptr.A as a struct typeA pointer */
else if(band == 2)
printf("B::a = %d", ptr.B->a); /* use ptr.B as a struct typeB pointer */
正如其他人所建议的,您可能需要更改您的设计,因为它有一些缺陷 但是,要解决出现的编译错误,可以执行以下操作:
printf("A:%d",(band == 1) ? ((struct typeA *)ptr)->a : ((struct typeB *)ptr)->a);
出现错误是因为您试图从void*
访问成员a
,而您这样做(ptr->a
)
你需要明确地说,
ptr
指向一个struct typeA
或struct typeB
在C中不需要强制转换(同样ptr
是void*
),请解释“不工作”。我否决了,因为你说你的代码不工作,但你没有说明原因,编译器给你的错误或警告是什么。提供此信息修改您的问题,我将删除我的否决票。停止播放malloc()
,但一定要为ptr
指定一个真实类型。如果事实上有很好的理由让ptr
bevoid*
那么为什么不分配两种尺寸中较大的一种呢?而且,“它不起作用”是对你问题的可怕描述。包括错误消息!哎呀,那不行。编译器需要知道ptr
指向什么类型。我想你可以在每次使用它时施放ptr
,但是哇,那会很难看。严格地说,您必须将指针指向其原始类型。(一个被广泛忽视的规则。)这是高级的C,现在,声明两个不同类型的指针。if(band==1){ptr=malloc(sizeof(struct typeA));/*…set A...*/printf(“A:%d\n,((struct typeA*)ptr)->A);}如果(band==2){ptr=malloc sizeof(struct typeB));printf
类型不匹配,但void*
是最通用的指针类型,因此将指向任何其他类型的指针分配给void*
应该没有问题,或者我错了吗?不是选民。