5

memcmpfromを使用する (C で) 配列を比較するためのデファクト メソッドはありstring.hますか?

単体テストで int と double の配列を比較したい

次のようなものを使用するかどうかはわかりません。

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ことは、一般的には良い考えではありません。より複雑なものから始めて、そこから下に進みましょう。


intとについて言及されましたが、まず、型の配列を比較するなど、一般的な解決策としてdouble集中したいと思います。memcmp

struct {
    char c;
    // 1
    int i;
    // 2
}

ここでの主な問題は、実装が場所 1 と 2 の構造体にパディングを自由に追加できることであり、重要なビットが完全に一致していても、バイトごとの比較が潜在的に偽になる可能性があります。


これでダブルスにダウン。そこにはパディングがないので、これはより良いと思うかもしれません。しかし、他にも問題があります。

1 つ目は、値の処理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

違いを示しています。

2つ目は、プラスマイナスゼロの扱いです。これらは比較のために等しいと見なされるべきですが、ビットパターンが異なるため、異なるmemcmpと言えます。

上記のコードのd1との宣言/初期化を次のように変更します。d2

 double d1 = 0.0, d2 = -d1;

これを明らかにします。


したがって、構造体と double に問題がある場合は、整数は問題ありません。結局のところ、それらは常に 2 の補数ですよね?

いいえ、実際にはそうではありません。ISO は、符号付き整数の 3 つのエンコーディング スキームの 1 つを義務付けており、他の 2 つ (1 の補数と符号/大きさ) は、プラスとマイナスの両方のゼロが存在するという事実である double と同様の問題に悩まされています。

そのため、それらは等しいと考えられるべきですが、やはりビット パターンは異なります。

符号なし整数の場合でも問題があります (符号付きの値でも問題になります)。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です。ただし、 double の配列にはお勧めできない理由については、この質問への回答を参照してください。memcmp

于 2011-12-06T12:35:17.563 に答える
2

memcmp は、指定されたサイズの数について 2 つのメモリ ブロックを比較します。

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 に答える