我正在编写用于在C语言中实现类型无关的链表的代码。这就是我想要做的。
创建一个可以存储以下任意一个的联合:int,char *,double,char。
union element { int num; char* str; double real; char alph; };
用于跟踪联合存储的元素的枚举。
enum { NUM, STR, REAL, CHAR };
将存储节点值的结构。
struct node { int type; union element data; struct node *next; };
由于我可能有多个列表,因此我还将为该节点创建一个容器,
struct list { struct node *head; };
现在,我想创建一个从列表中获取元素的函数。功能是
node* findkey(list *l, union element key)
{
node *i=list->head;
while(!i) {
if(i->data == key) {
return i;
i=i->next;
}
return NULL;
}
编译代码时,clang
抛出此错误,
linkedlist.c:33:11: error: invalid operands to binary expression ('union element' and
'union element')
if(i->data == key)
~~~~ ^ ~~~
1 error generated.
答案 0 :(得分:1)
这里
header?
其比较联合变量无效,如Harbison and Steele book所述
即使结构和工会,也无法比较平等 这些类型的分配是允许的。结构上的差距和 对齐限制导致的并集可以包含任意 值,并对此进行补偿将导致无法接受 相等比较或所有已修改操作的开销 结构和联合类型。
您可以像这样比较工会会员
if(i->data == key) {
答案 1 :(得分:-1)
将其移至答案,因为它不再适合注释。
此问题的根本原因是,如果并集成员的大小不同,则不能保证如果写入较小的成员然后比较较大的成员,则比较将成功。例如,如果您写了两个联合的alph
成员,然后比较了num
成员,则保存alph
的一个字节将正确比较,即使它们相等,num
中的其余字节可能会有所不同,从而导致“错误的不相等”结果。与写入num
成员,然后比较real
成员相同。
因此,为避免出现此问题,您需要首先比较两个type
值,并且只有在它们匹配时,才需要比较适当的一对联合成员。可以通过切换最轻松地选择要比较的成员。
node* findkey(list *l, union element key, int type)
{
node *i=list->head;
while(!i) {
// compare types first, assume no match if they differ
if(i->type != type) {
continue
}
switch (type)
{
case NUM:
if(i->data.num == key.num) {
return i;
}
break;
case STR:
...
case REAL:
...
case CHAR:
...
}
i=i->next;
}
return NULL;
}
我将添加一条注释,说明如何处理case STR:
取决于您想要的行为。如果要使两个字符串匹配,请使用strcmp()
,如果要它们引用相同的字符串,请在两个指针上使用==
。我怀疑前者将是一种更有用的处理方法,但值得注意的是确切的指针比较。类似于PHP中==
和===
之间的区别。