2

私はLCTHWチュートリアルに従っており、実行するタスクがあります。これはデータ構造です:

typedef struct DArray {
    int end;
    int max; 
    size_t element_size;
    size_t expand_rate;
    void **contents; 
} DArray;

私はtypedefを宣言しました:

typedef int (*DArray_compare) (const void *a, const void *b);

並べ替え関数を作成するときに、DArray_compareを渡します。問題は、このコンパレータの例を実行する方法がわからないことです。

私はこのようなことをしようとしました:

int compare(const void *a, const void *b)
{
  int i = (int)*a;
  int k = (int)*b;
  printf("%d %d\n", i, k);
  return i - k;
}

しかし、エラーが発生します:

error: operand of type 'void' where arithmetic or pointer type is required int i = (int)*a;

問題は、コンパレータの構造体とtypedefを変更せずに、intを比較するコンパレータを作成したいのですが、どうすればよいですか?

4

2 に答える 2

4
int i = *(int*)a;
// This one has more parens to make it really obvious what your intent is.
int k = *((int*)b);

2行目(k =)は、すべての括弧のcosを説明するのに最も簡単です。次のように書き直すことができます。

// Cast b from a pointer to a void into a pointer to an int.
int *X = (int*)b; 
// k = "what X is pointing to" or "the contents of X"
int k = *X;

編集:raluのコメントは、あなたがその力を持っているなら、はるかに安全な解決策であるすべてvoid*を変更することを示唆していると思います。int*

typedef int (*DArray_compare) (const int *a, const int *b);

int compare(const int *a, const int *b)
{
    int i = *a;
    int k = *b;
    ...
于 2012-10-02T07:18:47.647 に答える
2

構造体の配列用の標準Cライブラリと一緒に、bsearch()または標準Cライブラリから使用するための比較関数は、次のようになります。qsort()DArray

int compare(const void *a, const void *b)
{
    const DArray *d1 = a;
    const DArray *d2 = b;

    if (d1->end < d2->end)
        return -1;
    else if (d1->end > d2->end)
        return +1;
    else if (d1->max < d2->max)
        return -1;
    else if (d2->max > d2->max)
        return +1;
    else
        return 0;
}

明らかに、他のフィールドを比較する必要がある場合は、それらの比較を上記のフレームワークに非常に簡単に追加できます。関数の一般的な構造は、そのようなコンパレータを作成するための私の推奨される方法です。必要に応じて、割り当て行に明示的なキャストを追加できます。C ++はそれらを必要としますが、Cは必要ありません。

typedefコンパレータ自体との関連性は最小限であることに注意してください(ただし、関数ポインタとしてのコンパレータはそれに一致する必要がありますtypedef)。typedefこれはコンパレータが持つべきタイプですが、関数を書くときにその名前を使用することはできません。typedefソート関数の実装とその宣言でを使用できます。


intコンパレータの結果として2つの符号付きの値の差を返すと、未定義の動作が発生することをいくつかの場所で観察しました。

削除された回答へのコメントで、AR89は次のように質問しました。

減算の代わりに、ifステートメントの方が安全ですか?

はい。16ビットのint値があり、-30,000と+30,000を比較するとどうなるかを考えてみてください。符号付きオーバーフローが発生し、最初の値が2番目の値よりも小さい場合でも、コンパレータから正の値が返される可能性があります。同様の状況は、32ビットまたは64ビットの整数で発生する可能性があります。それらは比較的ありそうにありません。値が十分に範囲内にあることがわかっている場合は、問題ありません。ただし、汎用コードの場合は、区分的比較を行う必要があります。

if (i < k)
    return -1;
else if (i > k)
    return +1;
else
    return 0;

iとの値に関係なく機能するためkifまた、比較は型に対しても確実に機能しunsigned intますが、減算は実際には機能しないことに注意してください(結果は常にゼロまたは正になります)。

于 2012-10-02T07:19:17.173 に答える