5

用于比较数组(在 C 中)的事实方法是memcmpfromstring.h吗?

我想在单元测试中比较整数和双精度数组

我不确定是否使用类似的东西:

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)类型函数?

4

5 回答 5

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;
}
于 2011-12-06T12:34:23.907 回答
6

使用memcmp通常不是一个好主意。让我们从更复杂的开始,然后从那里开始。


尽管您提到了intand 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也可能是个坏主意。

于 2015-04-17T05:01:46.873 回答
5

在您的代码中替换memset为,它可以工作。memcmp

在您的情况下(因为两个数组数组的大小相同并且在编译期间已知)您甚至可以执行以下操作:

memcmp(a, b, sizeof(a));
于 2011-12-06T12:34:12.043 回答
3

您正在寻找的功能是memcmp不是 memset请参阅这个问题的答案,了解为什么它可能不是一个memcmp双打数组的好主意。

于 2011-12-06T12:35:17.563 回答
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;
  }
}
于 2011-12-06T13:05:52.873 回答