4

それは私だけですか、それともプログラミングパールのこのコードは間違っています(クイックソートは2つのconst voidを望んでいますか?)もしそうなら、私の解決策は正しいですか?謝罪、ただ学んで...

int wordncmp(char *p, char* q)
{   int n = k;
    for ( ; *p == *q; p++, q++)
        if (*p == 0 && --n == 0)
            return 0;
    return *p - *q;
}

int sortcmp(char **p, char **q)
{   return wordncmp(*p, *q);
}
...

qsort(word, nword, sizeof(word[0]), sortcmp);

これは解決策ですか?

int sortcmp(const void *p, const void *q)
{   return wordncmp(* (char * const *) p, * (char * const *) q);
}
4

2 に答える 2

7

最初のコードサンプルは、おそらく事実上すべてのコンパイラとCPUで動作します。ただし、C標準に従って文字を使用する場合、技術的には未定義の動作になります。

あなたが言ったように、への最後の引数qsort()は、タイプの2つの引数を取る関数へのポインタconst void*です。 sortcmpさまざまな引数を取ります。コンパイラ、互換性のない型シグニチャなどについて警告を出す必要があります。いずれにせよ、あるタイプの関数から別のタイプの関数へのキャストが実行されています。

C標準では、関数ポインターを異なるタイプの他の関数ポインターにキャストできると規定されていますが、キャストされた関数ポインターを逆参照して呼び出すことはできません。ただし、関数ポインタを元の型に再キャストすると、動作が定義されている関数を呼び出すと、元の関数が呼び出されます。

int (*)(char**, char**)aからaにキャストし、int (*)(const void*, const void*)最終的には、qsort()にキャストし直さずにコンパレータ関数を呼び出すためint (*)(char**, char**)、これは未定義の動作です。

ただし、事実上すべてのアーキテクチャで、achar **とaconst void*は同じように表されるため、関数呼び出しはほとんど常に機能します。

定義された動作を取得する場合は、コンパレータ関数に適切な型シグネチャがあることを確認してから、引数を適切な型にキャストできます。あなたの解決策は正確に正しく、そこでのC標準に違反していません。-正しさ-でよくやったconst-多くの人は正確に何char * const *を意味するのか理解していません。

パラメータを変更していないので、wordncmp()パラメータを取得する必要もあります。const char*

補足:技術的には、関数ポインターをデータポインター(例:)にキャストしvoid*たり、その逆を行ったりすることはできません。この標準では、関数ポインタとデータポインタのサイズを変えることができます。お使いのコンピューターで動作する場合でも、常に動作することが保証されているわけではありません。

于 2009-07-02T02:26:26.637 に答える
2

あなたは正しいです、の署名は期待するsortcmpものと一致しません。qsortあなたの訂正は正しいです。wordcmpまた、途中constで技術的に一部の-nessを失っているので、-correctにする必要があります。const

int wordncmp(const char *p, const char* q)
于 2009-07-02T02:26:56.840 に答える