使用memcmp
通常不是一个好主意。让我们从更复杂的开始,然后从那里开始。
尽管您提到了int
and double
,但我首先想将注意力集中在memcmp
一个通用解决方案上,例如比较类型的数组:
struct {
char c;
// 1
int i;
// 2
}
主要问题是实现可以自由地在位置 1 和 2 的结构中添加填充,即使重要位完全匹配,字节比较也可能是错误的。
现在降为双打。您可能会认为这更好,因为那里没有填充。然而还有其他问题。
首先是NaN
价值观的处理。IEEE754 竭尽全力确保它NaN
不等于任何其他值,包括它自己。例如,代码:
#include <stdio.h>
#include <string.h>
int main (void) {
double d1 = 0.0 / 0.0, d2 = d1;
if (d1 == d2)
puts ("Okay");
else
puts ("Bad");
if (memcmp (&d1, &d2, sizeof(double)) == 0)
puts ("Okay");
else puts
("Bad");
return 0;
}
将输出
Bad
Okay
说明差异。
二是正负零的处理。为了比较的目的,这些应该被认为是相等的,但是由于位模式不同,memcmp
会说它们是不同的。
将上述代码d1
的声明/初始化更改为:d2
double d1 = 0.0, d2 = -d1;
将使这一点清楚。
所以,如果结构和双打有问题,那么整数肯定是可以的。毕竟,它们总是二的补码,是吗?
不,实际上他们不是。ISO 规定了有符号整数的三种编码方案之一,另外两种(一个补码和符号/大小)与双精度数存在类似的问题,即正负零都存在。
因此,虽然它们可能应该被认为是相等的,但位模式又是不同的。
即使对于无符号整数,您也会遇到问题(对于有符号值也是一个问题)。ISO 声明这些表示可以具有值位和填充位,并且填充位的值是未指定的。
因此,即使对于看似最简单的情况,memcmp
也可能是个坏主意。