提问人:Hans Sjunnesson 提问时间:9/27/2008 更新时间:12/24/2017 访问量:261615
你如何比较 C 语言中相等的结构?
How do you compare structs for equality in C?
答:
C 没有提供任何语言工具来执行此操作 - 您必须自己完成并逐个比较每个结构成员。
评论
0.0, -0.0 NaN
memcmp()
int
calloc()
如果你经常这样做,我建议你写一个函数来比较这两种结构。这样,如果您更改了结构,则只需在一个地方更改比较即可。
至于怎么做......您需要单独比较每个元素
评论
您可能很想使用 ,但它可能并非在所有情况下都有效。编译器可以向结构添加对齐缓冲区空间,并且不能保证在缓冲区空间中的内存位置找到的值是任何特定值。memcmp(&a, &b, sizeof(struct foo))
但是,如果在使用结构之前使用结构的完整大小,则可以进行浅层比较(如果结构包含指针,则仅当指针指向的地址相同时,它才会匹配)。calloc
memset
memcmp
评论
memcmp
memcmp
您不能使用 memcmp 来比较结构的相等性,因为结构中的字段之间可能会随机填充字符。
// bad
memcmp(&struct1, &struct2, sizeof(struct1));
对于这样的结构,上述操作将失败:
typedef struct Foo {
char a;
/* padding */
double d;
/* padding */
char e;
/* padding */
int f;
} Foo ;
为了安全起见,您必须使用成员比较。
评论
如果结构只包含原语,或者你对严格相等感兴趣,那么你可以做这样的事情:
int my_struct_cmp(const struct my_struct * lhs, const struct my_struct * rhs) { return memcmp(lhs, rsh, sizeof(struct my_struct)); }
但是,如果您的结构包含指向其他结构或联合的指针,则需要编写一个函数来正确比较基元,并根据需要对其他结构进行比较调用。
但是请注意,作为 ADT 初始化的一部分,您应该使用 memset(&a, sizeof(struct my_struct), 1) 将结构的内存范围归零。
请注意,您可以在非静态结构上使用 memcmp(),而无需 担心填充,只要不初始化 所有成员(一次)。这是由 C90 定义的:
http://www.pixelbeat.org/programming/gcc/auto_init.html
评论
{0, }
这取决于你问的问题是否是:
- 这两个结构是同一个对象吗?
- 它们有相同的价值吗?
若要确定它们是否是同一对象,请比较指向两个结构的指针是否相等。 如果你想从总体上找出它们是否具有相同的价值,你必须做一个深入的比较。这涉及比较所有成员。如果成员是指向其他结构的指针,则也需要递归到这些结构中。
在结构不包含指针的特殊情况下,您可以执行 memcmp 来对每个结构中包含的数据执行按位比较,而无需知道数据的含义。
确保您知道“等于”对每个成员意味着什么 - 对于整数来说很明显,但当涉及到浮点值或用户定义类型时,则更加微妙。
memcmp
不比较结构,比较二进制文件,结构中总是有垃圾,因此比较总是出来 False。memcmp
逐个元素比较它是安全的,不会失败。
评论
如果 2 个结构变量是用 calloc 初始化的,或者它们被 memset 设置为 0,那么你可以将你的 2 个结构与 memcmp 进行比较,而不必担心结构垃圾,这将使你获得时间
此兼容示例使用 Visual Studio Microsoft 中的 #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))) {
/* ... */
}
}
评论
@Greg在一般情况下必须编写显式比较函数是正确的。
如果出现以下情况,则可以使用:memcmp
- 结构不包含可能是 的浮点字段。
NaN
- 结构不包含填充(与 clang 一起使用来检查这一点),或者结构在初始化时显式初始化。
-Wpadded
memset
- 没有具有不同但等效值的成员类型(如 Windows)。
BOOL
除非您正在为嵌入式系统编程(或编写可能在嵌入式系统上使用的库),否则我不会担心 C 标准中的一些极端情况。任何 32 位或 64 位设备上都不存在近指针与远指针的区别。据我所知,没有一个非嵌入式系统有多个指针。NULL
另一种选择是自动生成相等函数。如果以简单的方式布置结构定义,则可以使用简单的文本处理来处理简单的结构定义。您可以将 libclang 用于一般情况——因为它使用与 Clang 相同的前端,因此它可以正确处理所有极端情况(除非出现错误)。
我还没有见过这样的代码生成库。但是,它看起来相对简单。
但是,这种生成的相等函数经常在应用程序级别做错误的事情。例如,应该浅比较还是深入比较 Windows 中的两个结构?UNICODE_STRING
评论
memset
评论