用于比较数组(在C中)以使用memcmp
中的string.h
的defacto方法吗?
我想在单元测试中比较整数和双精度数组
我不确定是否使用类似的东西:
double a[] = {1.0, 2.0, 3.0};
double b[] = {1.0, 2.0, 3.0};
size_t n = 3;
if (! memcmp(a, b, n * sizeof(double)))
/* arrays equal */
或写一个定制的is_array_equal(a, b, n)
类型函数?
答案 0 :(得分:9)
memcmp
会进行完全比较,这对浮点数来说很少有好处,也不会遵循NaN!= NaN的规则。对于排序,这很好,但出于其他目的,您可能会进行近似比较,例如:
bool dbl_array_eq(double const *x, double const *y, size_t n, double eps)
{
for (size_t i=0; i<n; i++)
if (fabs(x[i] - y[i]) > eps)
return false;
return true;
}
答案 1 :(得分:5)
在代码中将memset
替换为memcmp
,然后就可以了。
在您的情况下(因为两个数组数组的大小相同且在编译期间已知)您甚至可以这样做:
memcmp(a, b, sizeof(a));
答案 2 :(得分:5)
使用memcmp
通常不是一个好主意。让我们从更复杂的开始,然后从那里开始工作。
虽然您提到了int
和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
也可能是一个坏主意。
答案 3 :(得分:3)
您正在寻找的功能是memcmp
,不是 memset
。请参阅this question的答案,了解尽管memcmp
一系列双打可能不是一个好主意。
答案 4 :(得分:2)
memcmp将两个内存块与给定的大小进行比较
memset用于初始化缓冲区,其值为给定的大小
缓冲区可以在不使用memcmp的情况下进行比较。对于不同的数据类型,可以更改相同的内容。
int8_t array_1[] = { 1, 2, 3, 4 }
int8_t array_2[] = { 1, 2, 3, 4 }
uint8_t i;
uint8_t compare_result = 1;
for (i = 0; i < (sizeof(array_1)/sizeof(int8_t); i++)
{
if (array_1[i] != array_2[i])
{
compare_result = 0;
break;
}
}