• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:bsearch関数の呼び出しで)

C言語のbsearch関数とは?引数についての疑問も解説

επιστημη(@episteme)の回答

回答No.2

#include <stdio.h> #include <stdlib.h> int int_cmp(const int* x, const int* y) { return *x - *y; } int main() { int x[] = { 1, 3, 5, 7, 9, 11 ,13 }; int nx = 7; int ky = 11; int* p; p = bsearch(&ky,x,nx,sizeof(int), (int (*)(const void *,const void *))int_cmp ); if ( p != NULL ) { printf("%d found at x[%d]\n", *p, p-x); } return 0; } > (int (*)(const void *,const void *))int_cmp の部分なのですが、まず戻り値をキャストするなら > int (*)ではなく(int *)ではないでしょうか。 > それとint_cmpは比較関数なのですが、引数が左側に来る、というところが納得できません。 int_cmp は"引数として const int* を2つ取り、intを返す関数"です。 ここでは int_cmp をキャストしています。 int_cmpの戻り値をキャストしているのでは「ありません」。 bsearchの第5引数に与えるのは"引数として const void* を2つ取り、intを返す関数"でなくてはなりません。 int_cmpはそのままでは型が一致しないため、"引数として const void* を2つ取り、intを返す関数"にキャスト しています。引数が左側に来ているのでは「ありません」 int (*)(const void *,const void *) にキャストしているのです。 > ソースファイルをcppのままだとコンパイルできませんでした C++はCに比べて型に厳しいため、(bsearchの返す)void*からint*への暗黙の型変換を許しません。 正しくは: p = (int*)bsearch(&ky,x,nx,sizeof(int),...

tranceporter
質問者

補足

すいませんありがとうございます。 まずcppでコンパイルできなかった理由はわかりました。 しかしint (*)(const void *,const void *))int_cmp のまず int (*) がわかりません。 *は(よりも優先順位が低いため、というのは調べたのですが (int *)と書いたらエラーでしょうか。 > >bsearchの第5引数に与えるのは"引数として const void* を2つ取り、intを返す関数"でなくてはな>りません。 >int_cmpはそのままでは型が一致しないため、"引数として const void* を2つ取り、intを返す関>>数"にキャスト >しています。引数が左側に来ているのでは「ありません」 int (*)(const void *,const void *) に>>キャストしているのです。 関数をキャストというのは初耳で難しいのですが int (*)(const void *,const void *)  と書くと2つのvoidがたを引数にし、int型ポインタを返す関数にint_cmpが変化するわけですね?? それなら、int_cmpの宣言のときにint int_cmp(void *x,void *y) と書いたらよい話ではないかと考えてしまいます。

関連するQ&A

  • bsearch関数2回目

    前回回答いただいた皆さんありがとうございました。 自分なりに勉強したところ、柴田望洋著 新・明解C言語によるアルゴリズムとデータ構造 のp105に解説を発見し、kmeeさんの回答からキャストの定義を学び、理解できました。 第5引数の比較関数なのですが、定義で int *int_cmp(const int *a, const int *b) とint_cmpの前に*は要らないのでしょうか。。ただ第5引数にint_cmpと書けばint_cmp関数の先頭アドレスが参照されることになってるんでしょうか。 それと MillenniuM さんの宿題のような比較関数 int int_cmp(const void* x, const void* y) { return *(int*) x - *(int*) y; } の*(int*)x - *(int*)y; の部分をVisualStudio2013でデバッグ解析しようとすると msvcr120d.i386.pdbが見つからない~というようなことを言われてその部分の動作を解析できません。。(コンパイルはできます) このvsでコンパイルできない理由と意味をどなたかご教授頂けないでしょうか

  • qsortの関数ポイントについて

    qsortの関数ポイントについて int int_cmp(const int *a, const int *b) { ------ } main { qsort(x,nx,sizeof(int),(int (*) (const void *, const void * )) int_cmp); 上記の(1)関数のポイント,(int (*) (const void *, const void * )) int_cmpを  普通の(2)関数ポイント(* int_cmp) (const void *, const void * )で呼べない  理由 、また、(1)(2)は、同じ意味でしょうか、教えて頂きたい。

  • qsortの関数について

    qsortの関数について 下記のようにある本に関数の呼ぶ時、関数名(int_cmp)が引数(const void *, const void *)の後に書かれて理由を教えて頂きたい。よろしくお願いします。 質問のプログラム int int_cmp(const int *a ,const int *b) { ------ } int main { qsort(x, nx , y, (int (*)(const void *, const vois *))int_cmp);

  • こんなコンパイルエラーがでます。

    OS:WinNT4.0 環境:VC++6.0 MFC コンパイル時に次のエラーが出て来ました。 error C2664: 'qsort' : 4 番目の引数を 'int (const void *,const void *)' から 'int (__cdecl *)(const void *,const void *)' に変換できません。 (新しい機能 ; ヘルプを参照)スコープ内でこの名前を持つ関数でターゲット型に一致するものはありません。 qsort関数の引数関数を'int xxxxxxx(const void *,const void *)に宣言したところこのエラーが出てきました。 何がなんだかさっぱりわかりません。 ぜひお願いします。

  • CからC++の関数呼び出し

    CからC++の関数を呼び出して値を取得したいのですが、コンパイルエラーになってしまいます。 呼び出す関数内でさらに同じクラスの関数を呼び出して値をreturnしたいだけなのですが、 ご教示願います。 ソースは下記のような感じです。 Cソース(AAA.c) main(){ ・・・・・ if ( funcA() ){ ・・・・ } } C++ソース(BBB.cpp) int clsB::funcB { return iflg; } extern "C" { int funcA() { return funcB(); } } ※上記externは特に何かの関数内に書いているわけではありません。 C++ヘッダ(BBB.hpp) class clsB : public XXX { private: int iflg; ・・・・ public: int funcB(); ・・・・ } 上記にコンパイルすると、 externしている箇所でfuncBはスコープにありません?のようなエラーが出てしまいます。 ラッパ関数を使って使用するなどと聞いたのですが、やり方がいまいちわかりません。 どうか教えていただけますでしょうか。 また、他にやり方があるかと思いますが、いいやり方があれば教えていただけると幸いです。 以上です、よろしくお願いいたします。 不足内容あれば指定願います。

  • qsortについて

    qsort()で構造体をソートする時に、qsortの第3,4引数時の、「size t_t size, int (*cmp)(const void *a, const void *b)」の使い方が分かりません。 何故これを使ってソートが出来るのでしょうか?そもそも、構造体を送った時に、自作関数内での書き方にも疑問があります。 int main(void){ MAX dt[5]={・・・・}; //構造体変数宣言 ・・・・・ qsort(dt,5,sizeof(MAX),sum); //(*1) .... return 0; } int sum(const void *a, const void *b){ MAX *p1 = (MAX *)a; //(*2) MAX *p2 = (MAX *)b; //(*2) ・・・・ return ~; } ---------------------------------------------------- *1: 第3引数のsizeof(MAX)って何ですか? *2: 例えばint型が渡されてreturnする場合は、「return *(int *)a - *(int *)b 」でいいのに、   何故構造体の場合はこう書かないといけないのですか?

  • qsortの引数について

    以下のプログラムがあります。 int compare( const char **name1, const char **name2 ) { return strcmp( *name1, *name2 ); } int main( void ) { char *names[] = { "rand", "calloc", "malloc" }; int num = sizeof names / sizeof names[0]; qsort( names, num, sizeof( names[0] ), (int (*)(const void *, const void * ))compare ); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~この部分 return 0; } 上の「~~~」の上の部分のqsort関数の第4引数のキャストの意味が 分かりません。なぜ関数の前に引数が書かれるのでしょうか? またintの後にある(*)は「int型のポインタ」と言う意味なのか、 compare関数のポインタなのかも分かりません。 ご回答よろしくおねがいします。

  • 参照型の変数をポインタ引数を持つ関数に引数を書く方法

    C++の参照を使って以下のソースを試したのですが、 memmoveの引数のところでエラーが出ます。 memmoveの引数はポインタ型で合いません。 実体コピーしたい場合、どのようにすればよいのでしょうか? const AA &aとすれば、a自体が関数内で書き換わる心配がないので、 C++の参照型は、ポインタより安全と理解しているのですが その認識は間違っていないでしょうか? struct aa{ int x; int y; }AA; void test(AA &a) { AA b; memmove(b, a, sizeof(AA)); } void main(){ AA c; test(c); }

  • なんでchar型なんでしょうか??

    なぜここ(☆☆)で char型なのかが よく・・いやさっぱりわかりません。 他の型ではだめなんでしょーか? この関数自体は挿入ソートだとわ思われるんで なんとなくこの☆☆(から以下三行あたりまで) のところの動作の意味はわかるんですが なぜchar型でなくてはならないのかが。 知っている方いたら どうか教えてください。 typedef User* PUser; typedef int (*CFT)(const void*, const void*); void ssort(void* base, unsigned int n,        unsigned int sz, CFT cmp) {    for (int i = 0; i < n - 1; i++) for (int j = n - 1; i < j; j--) {          char* pj = (char*)base + j * sz; //←ここ☆☆          char* pj1 = pj - sz;  //とここ☆☆           if (cmp(pj, pj1) < 0) { for (int k = 0; k < sz; k++) { char temp = pj[k]; pj[k] = pj1[k]; pj1[k] = temp; }     }    } /* ssort関数の引数の関数ポインタで 利用される比較関数 */ int cmp1(const void* p, const void* q) { return strcmp(PUser(p)->name, PUser(q)->name); } int cmp2(const void* p, const void* q) { return PUser(p)->dept - PUser(q)->dept; }

  • main関数の事についてお聞きします。

    Windowsのプログラムを書くとき、下のようにキッチリ戻り値や引数を書かなくてはならないのに int WINAPI WinMain( HINSTANCE hInstance, // 現在のインスタンスのハンドル HINSTANCE hPrevInstance, // 以前のインスタンスのハンドル LPSTR lpCmdLine, // コマンドライン int nCmdShow // 表示状態 ); C言語で書かれたプログラムは int main(int argc, char *argv[]) ではなく、 int main(void) や void main(void) または int main() や main() だけのモノなど、 いろいろです。 main関数は、関数なのに戻り値や引数を省略して書ける仕様なのは、なぜなのか? ちょっと疑問に思ったのでこちらにお尋ねしました。