質問: reinterpret_cast( bsearch(&no, x, nx, sizeof(int), /*ここです。*/ reinterpret_cast(int_cmp)) ); /* */ if (p != NULL) { cout << "x[" << (p - x) << "]が一致します。\n"; } else { cout << "見つかりません\n"; } _getch(); return 0; } ```
回答: コメント欄にて質問が更新されているのでそっちに対応 > > なぜconst void* なのでしょうか?引数をvoidにしてししまうと値を渡せないんと思うんですけど > > > 比較関数の引数は `void` ではなくて `void*` ですよ(事の本質に関係ないので `const` は省略)この2つはまったく違います。結局のところわかっていないのはここなのでは? [c](/questions/tagged/c "'c' のタグが付いた質問を表示")/[c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") において `void*` とはポインタの総称型とでも呼ぶべきものです。 - 任意の型のオブジェクトへのポインタ値を `void*` に格納できる - `void*` の値から、元の型の値に戻すことができる ことが言語仕様で保証されています。 (JIS X 3014:2003 4.10-2, 5.2.9-10) `bsearch` や `lfind` や `qsort` は任意の型に対して処理ができるようにわざと `void*` を使う設計となっています。 下記では、短くしたい(この回答で書きたい重要部分でない)ためオーバーフローするとダメなコードをわざと提示しています。実用的なコードにするにはリンク先参照のこと。 ref. C言語のPOSIX定義関数のlfindで配列要素の検索がうまくできているか自信がない `int` の比較を行う関数なら ``` int int_comparator(const void* lp, const void* rp) { int lval=*(const int*)lp; // void* → int* へ戻すことができる int rval=*(const int*)rp; return lval-rval; } ``` のように `void*` から `int*` に戻すキャストを書けばよいのです。 `mytype` の比較を行う関数なら ``` int mytype_comparator(const void* lp, const void* rp) { const mytype* l=(const mytype*)lp; // void* → mytype* へ戻すことができる const mytype* r=(const mytype*)rp; return l->foo-r->foo; // mytype にメンバ foo があるものとする } ``` 上記 `int_comparator` や `mytype_comparator` なら `bsearch` にキャストなしに直接渡すことができ、かつ、動くことが保証されています。逆に、提示の `int_cmp` は `bsearch` が要求している関数の型と違うので `int_cmp` へのポインタをキャストして無理やり渡しても動作保証はありません(ほとんどの場合には問題ないですけど)。関数ポインタの型表記は難しくて読みづらいのですが、それについては既に Hideki さんから回答がありますよね。 さてここで話題になっている `bsearch` や `lfind` は `qsort` は [c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") が登場する前からある、とてつもなく古いものです。そのためキャストをわざわざ明示する必要があったり(ソースコードが見づらくなる)、関数ポインタ経由で比較を行ったり(遅い!)、慣れないと理解しがたい、使いにくい(現に今質疑応答の対象となってますよね)のです。 [c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") ならもっと良い(わかりやすくて高速動作するであろう)方法が用意されています。過去の遺物に手を出さずに、新しい良い方法を使ってみませんか?