プログラミング真珠中のqsort関数でエラーが発生しましたか?
-
21-08-2019 - |
質問
それは私だけか、プログラミング真珠でこのコードは>(クイックソートはなし、2つのconstボイドを望んでいる?)もしそうなら間違っている、私の解決策の権利がありますか?謝罪、ちょうど学習...
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);
}
解決
最初のコードサンプルは、おそらくほとんどすべてのコンパイラとCPUで動作します。あなたは手紙にCの標準に従っている場合しかし、それは、技術的に未定義の動作です。
あなたが言ったように、、qsort()
の最後の引数は、型const void*
の二つの引数を取る関数へのポインタです。 sortcmp
は異なる引数を取ります。あなたのコンパイラは、ははあなたに互換性のないタイプの署名か何かについての警告を与える必要があります。いずれの場合においても、キャストは別の型の機能に一種類の機能から行われている。
Cの標準では、さまざまな種類の他の関数ポインタに関数ポインタをキャストすることができますように指定していますが、キャスト関数ポインタを逆参照して呼び出すことはできません。あなたはしかし、元の形に戻す関数ポインタを再キャスト、その定義された振る舞いを呼び出す - 。それは元の関数を呼び出します。
あなたはint (*)(char**, char**)
にint (*)(const void*, const void*)
からキャストしている、そして、最終的にqsort()
がint (*)(char**, char**)
に戻ってそれをキャストすることなく、あなたのコンパレータ機能を呼び出しているので、それは未定義の動作です。
しかし、事実上すべてのアーキテクチャであるため、char **
とconst void*
は、関数呼び出しがほとんど常に動作します同じように表現されます。
あなたが定義された動作を取得したい場合は、あなたのコンパレータ機能は、適切なタイプの署名を持っていることを確認する必要があり、その後、あなたは適切な型に引数をキャストすることができます。あなたのソリューションは、まさに正しく、そこにCの標準に違反しません。まあconst
-正確に行われ - 。多くの人々は手段をchar * const *
正確に理解していない
また、あなたはパラメータを変更していないので、wordncmp()
は、const char*
のパラメータを取る確認する必要があります。
サイドノート:あなたはまた、技術的にデータポインタ(例えばvoid*
)またはその逆への関数ポインタをキャストすることはできません。標準は、異なるサイズを持つように関数ポインタとデータポインタが可能になります。それはあなたのコンピュータ上で動作する場合であっても、それは常に動作する保証はない。
他のヒント
あなたが正しい、sortcmp
のための署名はqsort
が期待するものと一致しません。あなたの補正は権利です。あなたが技術的に道に沿ってwordcmp
ネスの一部を失っているようconst
もconst
-正しいなされるべきである。
int wordncmp(const char *p, const char* q)