如何比较标准C中两个相等的struct实例?
当前回答
这个兼容的例子使用了来自Microsoft Visual Studio的#pragma包编译器扩展,以确保结构成员尽可能紧密地打包:
#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的浮点字段。 结构体不包含填充(使用- wpadding with clang来检查)或者结构体在初始化时显式地使用memset初始化。 没有成员类型(如Windows BOOL)具有不同但等效的值。
除非你正在为嵌入式系统编程(或者编写一个可能用于嵌入式系统的库),否则我不会担心C标准中的一些极端情况。近指针和远指针的区别在任何32位或64位设备上都不存在。我所知道的非嵌入式系统中没有多个NULL指针。
另一种选择是自动生成相等函数。如果以简单的方式布局结构定义,则可以使用简单的文本处理来处理简单的结构定义。对于一般情况,您可以使用libclang—因为它使用与Clang相同的前端,所以它可以正确地处理所有边缘情况(排除错误)。
我还没有见过这样的代码生成库。然而,它看起来相对简单。
然而,这种生成的相等函数在应用程序级别上经常会做错误的事情。例如,Windows中的两个UNICODE_STRING结构应该进行浅比较还是深比较?
C语言没有提供这样做的语言工具——你必须自己做,并逐个比较每个结构成员。
memcmp不比较结构,memcmp比较二进制,结构中总是有垃圾,因此在比较中总是输出False。
逐个元素比较它是安全的,不会失败。
这个兼容的例子使用了来自Microsoft Visual Studio的#pragma包编译器扩展,以确保结构成员尽可能紧密地打包:
#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))) {
/* ... */
}
}
注意,可以在非静态结构上使用memcmp() 担心填充,只要你没有初始化 所有成员(同时)。这是C90定义的:
http://www.pixelbeat.org/programming/gcc/auto_init.html