如何比较标准C中两个结构的实例是否相等?
答案 0 :(得分:176)
C没有提供任何语言设施 - 你必须自己做,并按成员比较每个结构成员。
答案 1 :(得分:100)
您可能很想使用memcmp(&a, &b, sizeof(struct foo))
,但它可能无法在所有情况下使用。编译器可能会将对齐缓冲区空间添加到结构中,并且在缓冲区空间中的内存位置找到的值不能保证是任何特定值。
但是,如果您在使用结构之前使用calloc
或memset
完整尺寸的结构,那么可以进行浅比较memcmp
(如果你的结构包含指针,只有当指针指向的地址相同时才会匹配)。
答案 2 :(得分:20)
如果你做了很多我建议写一个比较两种结构的函数。这样,如果你改变了结构,你只需要在一个地方改变比较。
关于如何做到....你需要单独比较每个元素
答案 3 :(得分:17)
由于结构中字段之间存在潜在的随机填充字符,因此无法使用memcmp来比较结构的相等性。
// bad
memcmp(&struct1, &struct2, sizeof(struct1));
对于像这样的结构,上面的内容会失败:
typedef struct Foo {
char a;
/* padding */
double d;
/* padding */
char e;
/* padding */
int f;
} Foo ;
您必须使用成员比较才能安全。
答案 4 :(得分:5)
请注意,您可以在非静态结构上使用memcmp() 担心填充,只要你不初始化 所有成员(立刻)。这由C90定义:
答案 5 :(得分:5)
@Greg是正确的,在一般情况下必须编写显式比较函数。
可以使用memcmp
if:
NaN
的浮点字段。-Wpadded
来检查)或者在初始化时使用memset
显式初始化结构。BOOL
)具有不同但等效的值。除非您正在为嵌入式系统编程(或编写可能在其上使用的库),否则我不会担心C标准中的一些极端情况。在任何32位或64位设备上都不存在近与远指针的区别。我所知道的非嵌入式系统没有多个NULL
指针。
另一种选择是自动生成相等函数。如果以简单的方式放置结构定义,则可以使用简单的文本处理来处理简单的结构定义。您可以将libclang用于一般情况 - 因为它使用与Clang相同的前端,它可以正确处理所有极端情况(禁止错误)。
我还没有见过这样的代码生成库。但是,它看起来相对简单。
但是,这种生成的相等函数通常也会在应用程序级别执行错误操作。例如,Windows中的两个UNICODE_STRING
结构应该浅或深吗?
答案 6 :(得分:2)
这取决于你问的问题是:
要确定它们是否是同一个对象,请将指向两个结构的指针进行比较。 如果您想要了解它们是否具有相同的值,则必须进行深入比较。这涉及比较所有成员。如果成员是指向其他结构的指针,则还需要递归到这些结构中。
在结构不包含指针的特殊情况下,您可以使用memcmp对每个数据中包含的数据进行按位比较,而不必知道数据的含义。
确保你知道'equals'对每个成员意味着什么 - 对于整数来说很明显,但在浮点值或用户定义的类型方面则更为微妙。
答案 7 :(得分:2)
memcmp
不比较结构,memcmp
比较二进制,并且结构中总是有垃圾,因此它在比较时总是出现错误。
逐个元素地比较它的安全性并且不会失败。
答案 8 :(得分:1)
如果结构只包含原语或者你对严格的相等感兴趣那么你可以这样做:
int my_struct_cmp(const struct my_struct * lhs, const struct my_struct * rhs) { return memcmp(lhs, rsh, sizeof(struct my_struct)); }
但是,如果你的结构包含指向其他结构或联合的指针,那么你需要编写一个正确比较基元的函数,并根据需要对其他结构进行比较调用。
但请注意,您应该使用memset(& a,sizeof(struct my_struct),1)将结构的内存范围归零,作为ADT初始化的一部分。
答案 9 :(得分:-1)
如果2个结构变量用calloc初始化,或者它们被memset设置为0,那么你可以将你的2个结构与memcmp进行比较,不用担心结构垃圾,这样你就可以赚取时间
答案 10 :(得分:-2)
此兼容示例使用Microsoft Visual Studio中的#pragma pack编译器扩展来确保结构成员尽可能紧密地打包:
#include <string.h>
#pragma pack(push, 1)
struct s {
char c;
int i;
char buffer[13];
};
#pragma pack(pop)
void compare(const struct s *left, const struct s *right) {
if (0 == memcmp(left, right, sizeof(struct s))) {
/* ... */
}
}