为了解释更多,我有两个结构 - '第一个'和第二个'有共同的变量' jack'并且' jill'。我想通过基于if-else条件的指针来打印插孔。 据我所知,在打印时我必须对void指针进行类型转换。但是指针指向struct 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
答案 0 :(得分:2)
您收到编译器警告,因为编译器不理解z->jack
,因为z
是void *
(请注意,声明a* z
和b* z
不是在if
和else
块的范围之外有效。
要解决此问题,您可以使用以下列表中所示的函数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 *
投射的几个地方,你会花很多时间调试正在进行的事情...... < / p>
现在我按照以下方式写这样的事情:
#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 one
和struct two
的公共部分。而不是将void *
转换为a *
或b *
a&#34;常见&#34;转换为struct header *
(或h *
)已完成。
通过这样做,您可以轻松扩展&#34;共同的属性&#34;结构或您可以使用此标头实现更多结构,函数printJack
仍然可以工作。此外,不再需要属性type
,因此更容易调用printJack
。您甚至可以更改jack
的类型,而无需在代码中的各个位置更改它。
但请记住,struct header
需要是您使用此机制的结构的第一个元素。否则你会得到一些惊喜,因为你使用的内存不包含struct header
的数据......