为啥我可以分配结构但不能比较它们

Posted

技术标签:

【中文标题】为啥我可以分配结构但不能比较它们【英文标题】:Why can I assign structs but not compare them为什么我可以分配结构但不能比较它们 【发布时间】:2010-12-25 08:59:35 【问题描述】:

尽管我是一名长期的 C 程序员,但我最近才知道可以直接将结构变量相互分配,而不是使用 memcpy:

struct MyStruct a,b;
...
a = b; /* implicit memcpy */

虽然这对 C 来说感觉有点“高级”,但它绝对有用。但是为什么我不能做相等和不等比较:

if (a == b) ...
if (a != b) ...

标准是否有充分的理由排除这一点?或者这是一个不一致的 - 否则非常优雅 - 标准?

我不明白为什么我可以替换我的 memcpy 以获得干净的任务,但我必须保留那些丑陋的 memcmp。

【问题讨论】:

+1 提出了一个让我受益匪浅的问题。 【参考方案1】:

根据comp.lang.c FAQ:

编译器没有好办法 实现结构比较 (即支持 == 运算符 结构)这是一致的 C的低级风味。一个简单的 逐字节比较可能会失败 在未使用的随机位上 结构中的“洞”(例如 填充用于保持对齐 后面的字段正确)。逐场比较可能需要不可接受的数量 大型结构的重复代码。 任何编译器生成的比较 不能指望比较 在所有适当的指针字段 案例:例如,通常 适合比较 char * 字段 使用 strcmp 而不是 ==。

如果您需要比较两个结构, 你必须编写自己的函数 为此,逐个字段。

【讨论】:

我知道这样做是有充分理由的。我只是忘记了结构上的洞。 谢谢。我理解填充参数。但是指针字段参数不是同样适用于赋值吗? 填充参数是有道理的,但指针比较位似乎很假。是的,您可能希望为包含指向字符串的指针的结构定义自己的比较函数,但对于独立指针也是如此。即:您可能想使用 strcmp 而不是 == 进行比较。 "如果编译器在分配时跳过填充..."。不必要。例如,如果最后有填充,我认为编译器可以在赋值时跳过它。假设它是合法的,那么复制它是没有意义的。但是因为您已经仔细编写了与平台无关的代码,所以您不知道最后有填充,所以您的 memcmp 将是 sizeof(struct MyStruct) 字节,并包含没有被复制的填充。 您可能还会考虑在结构中有联合时会发生什么。联合很容易复制,但很难比较。当然,逐个字段比较元素会很浪费,但是元素之间的大小/填充差异意味着您不能只比较任何一个元素。确定哪些字节是填充以及哪些是相关的变得非常棘手。

以上是关于为啥我可以分配结构但不能比较它们的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能动态分配这个结构字符串的内存?

为啥我不能在我的结构中打印名称?

Python list 可以在迭代期间发生变异,但不能在 deque 中发生变异。为啥?

Swift iOS - 我为啥可以循环遍历一组类对象并进行属性更改但不能更改结构[重复]

为啥可以将切片分配给空接口但不能将其强制转换为相同的空接口

安装了protege 4.2,建完本体后,点击OntoGraf标签,为啥不能显示定义的概念结构图呢?