正如大多数C程序员所知,你无法直接比较两种结构.
考虑:
void isequal(MY_STRUCT a, MY_STRUCT b)
{
if (a == b)
{
puts("equal");
}
else
{
puts("not equal");
}
}
Run Code Online (Sandbox Code Playgroud)
该a==b
比较将AFAIK扔在任何合理的C语言编译器编译错误,因为C标准不允许内置结构比较.使用memcmp的变通方法当然是一个坏主意,因为对齐,打包,位域等,所以我们最终逐个元素比较函数.
另一方面,它允许结构分配,例如a = b
完全合法.很明显,编译器可以相当简单地处理这个问题,为什么不进行比较呢?
我唯一的想法是结构分配可能与memcpy()非常接近,因为对齐等因素无关紧要.另一方面,比较可能更复杂.或者这是我缺少的东西?
显然,我知道通过元素比较做一个简单的元素不一定足够,例如,如果结构包含指向字符串的指针,但在某些情况下它会有用.
由于同样的原因memcmp
失败,因此不支持比较.
由于填充字段,比较将以不可预测的方式失败,这对于大多数程序员来说是不可接受的.赋值会更改不可见的填充字段,但无论如何它们都是不可见的,因此没有任何意外.
显然,您可能会问:那么为什么不填充所有填充字段呢?当然这会起作用,但它也会使所有程序为他们可能不需要的东西付费.
Oli Charlesworth在评论中指出,您可能会问:"为什么编译器不会为逐个成员的比较生成代码".如果是这样,我必须承认:我不知道 :-).如果只允许比较完整类型,编译器将拥有所有需要的信息.
我在C理由(C99理论基础V5.10),6.5.9中找到了这个:
C89委员会不止一次考虑允许比较结构的平等.这些建议在结构上的孔问题上失败了.两个结构的逐字节比较将要求确保将孔设置为零,以便所有孔都相等,这对于自动或动态分配的变量来说是一项艰巨的任务.
结构中联合类型元素的可能性使这种方法产生了不可克服的问题.如果不确保所有漏洞都设置为零,则必须准备实施以将结构比较分解为任意数量的成员比较; 因此,一个看似简单的表达式可能会扩展为大量的代码,这与C的精神背道而驰
用简单的英语:由于结构/联合可能包含填充字节,并且委员会没有强制执行这些以保存某些值,因此它们不会实现此功能.因为如果所有填充字节必须设置为零,则需要额外的运行时开销.
自动生成比较运算符不是一个好主意。想象一下比较如何对这种结构起作用:
struct s1 {
int len;
char str[100];
};
Run Code Online (Sandbox Code Playgroud)
这是像最大长度为100的字符串一样的pascal
另一种情况
struct s2 {
char a[100];
}
Run Code Online (Sandbox Code Playgroud)
编译器如何知道如何比较字段?如果这是NUL终止的字符串,则编译器必须使用strcmp或strncmp。如果是char数组,则编译器必须使用memcmp。
添加到现有的好的答案:
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?!
Run Code Online (Sandbox Code Playgroud)
这个问题本质上是由于工会无法存储/跟踪哪个成员是当前成员而产生的。