为什么C不提供结构比较?

时间:2011-08-24 16:45:49

标签: c

正如大多数C程序员所知,你无法直接比较两种结构。

考虑:

void isequal(MY_STRUCT a, MY_STRUCT b)
{
    if (a == b)
    {
        puts("equal");
    }
    else
    {
        puts("not equal");
    }
 }

a==b比较将AFAIK在任何合理的C编译器上抛出编译错误,因为C标准不允许内置结构比较。使用memcmp的解决方法当然是一个坏主意,因为对齐,打包,位域等,所以我们最终逐个元素比较函数。

另一方面,它允许结构分配,例如a = b完全合法。 很明显,编译器可以相当简单地处理这个问题,为什么不进行比较?

我唯一的想法是结构分配可能与memcpy()非常接近,因为对齐等因素并不重要。另一方面,比较可能更复杂。或者这是我缺少的东西?

显然,我知道通过元素比较做一个简单的元素并不一定足够,例如如果结构包含指向字符串的指针,但在某些情况下它会有用。

5 个答案:

答案 0 :(得分:9)

由于memcmp失败的原因相同,因此不支持比较。

由于填充字段,比较将以不可预测的方式失败,这对大多数程序员来说是不可接受的。赋值会更改不可见的填充字段,但无论如何它们都是不可见的,因此没有任何意外。

显然,您可能会问:那为什么不填充所有填充字段?当然这会起作用,但它也会使所有程序为他们可能不需要的东西付费。

修改

您可能会在评论中注意到

Oli Charlesworth:“为什么编译器不会为逐个成员的比较生成代码”。如果是这样的话,我必须承认:我不知道 :-)。如果编译器只允许比较完整类型,它将拥有所有需要的信息。

答案 1 :(得分:9)

正如其他人所提到的,这里是Harbison和Steele的C: A Reference Manual摘录:

  

即使允许对这些类型进行赋值,也无法比较结构和联合的相等性。由对齐限制引起的结构和联合中的间隙可能包含任意值,并且对此进行补偿会对相等比较或修改结构和联合类型的所有操作施加不可接受的开销。

答案 2 :(得分:6)

我在C理由(C99 rationale V5.10),6.5.9:

中找到了这个
  

C89委员会不止一次考虑允许比较结构   为了平等。这些建议在结构上的孔问题上失败了。按字节顺序   两个结构的比较需要确保将孔设置为零以便全部   对于自动或动态分配的变量,空洞会比较相等,这是一项艰巨的任务。

     

结构中联合类型元素的可能性引发了不可克服的问题   做法。如果没有确保所有漏洞都设置为零,那么实现就可以了   准备将结构比较分成任意数量的成员比较;   因此,一个看似简单的表达式可以扩展为大量的代码   与C的精神相反

用简单的英语:由于结构/联合可能包含填充字节,并且委员会没有强制执行这些以保存某些值,因此它们不会实现此功能。因为如果所有填充字节必须设置为零,则需要额外的运行时开销。

答案 3 :(得分:4)

自动生成比较运算符是个坏主意。想象一下比较如何对这个结构起作用:

struct s1 {
   int len;
   char str[100];
};

这是类似字符串的pascal,最大长度为100

另一个案例

struct s2 {
   char a[100];
}

编译器如何知道如何比较字段?如果这是一个以NUL结尾的字符串,则编译器必须使用strcmp或strncmp。如果这是char数组编译器必须使用memcmp。

答案 4 :(得分:1)

添加现有的好答案:

struct foo {
    union {
        uint32_t i;
        float f;
    } u;
} a, b;
a.u.f = -0.0;
b.u.f = 0.0;
if (a==b) // what to do?!

问题源于工会无法存储/跟踪哪个成员是最新的。