- ベストアンサー
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);
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
qsort()は、ソート対象の配列の型を規定していません。 どの型でも対応できるように、第4引数に書く比較用関数のプロトタイプは 「任意の型へのポインタを2個引数で受取り、int型を返す関数へのポインタ」という形をしています。 例示のコードではint型配列を対象としていますので、 比較用の関数int_cmp()の引数の型がint *になっています。
その他の回答 (6)
- titokani
- ベストアンサー率19% (341/1726)
引数が前にあるのではありません。 よく見てください。 > qsort(x, nx , y, (int (*)(const void *, const vois *))int_cmp); >int_cmp の引数(const void *a, const void *b)がint_cmpの前にあるのが、 勝手に、a,bを補ってはいけません。 「int (*)(const void *, const vois *)」 というのが、型なんです。複雑ではありますが、型は型です。この型でキャストするということです。
お礼
回答ありがとうございます。皆さんの回答のおかげで戻り値(int (*) ,引数(const void *, const vois *)の型でキャストしていることが 解りました。
- Yune-Kichi
- ベストアンサー率74% (465/626)
> int_cmp の引数(const void *a, const void *b)がint_cmpの前にあるのが、 > わかりません。 よく括弧の範囲を見てください。 (int (*)(const void *, const void *)) でひとまとまりです。つまり, int (*)(const void *, const void *) が型になります。
お礼
回答ありがとうございます。皆さんの回答のおかげで戻り値(int (*) ,引数(const void *, const vois *)の型でキャストしていることが 解りました。
- php504
- ベストアンサー率42% (926/2160)
関数ポインタには戻り値の型と引数の型が必要です (int (*)(const void *, const vois *))まとめて関数ポインタの型になります typedefで定義してみましたがどうでしょう #include <stdio.h> #include <stdlib.h> typedef int(*FUNCP) (const void *, const void *); int int_cmp(const int *a ,const int *b) { return *a - *b; } int main() { int x[10] = {4, 2, 3, 6, 3, 2, 1, 3, 5, 7}; int y = sizeof(int); int nx = 10; int i; qsort(x, nx , y, (FUNCP)int_cmp);//FUNCP型にキャスト for (i = 0; i < nx; i++) { printf("%d ", x[i]); } return 0; }
お礼
回答ありがとうございます。皆さんの回答のおかげで戻り値(int (*) ,引数(const void *, const vois *)の型でキャストしていることが 解りました。
- asuncion
- ベストアンサー率33% (2127/6289)
>int_cmp の位置が(const void *a, const void *b)の後にあるのは、何故でしょうか。 int_cmp関数のアドレス(int_cmp)を所定の形にキャストしているのです。 関数ではない、一般の変数の場合を考えてみます。 char型の変数cをint型にキャストして別の変数(例えばn)に代入するとき、 char c; n = (int) c; と書きますでしょう?これと同じ考え方です。
お礼
回答ありがとうございます、一般の変数のキャストは、わかりますが、 int_cmp の引数(const void *a, const void *b)がint_cmpの前にあるのが、 わかりません。よろしくお願いします。
- asuncion
- ベストアンサー率33% (2127/6289)
#1です。 #2さんの書かれているとおりであれば、例示のコードを 次のように修正しておくのがよさそうです。 int int_cmp(const void *a, const void *b) { const int *p = a, *q = b; /* ここで、int型のソートであることを明示 */ return *p < *q ? -1 : *p > *q ? 1 : 0; } int main(void) { /* 必要な、その他の記述を書く */ qsort(x, nx, y, int_cmp); return 0; }
お礼
回答ありがとうございます。皆さんの回答のおかげで戻り値(int (*) ,引数(const void *, const vois *)の型でキャストしていることが 解りました。
- Yune-Kichi
- ベストアンサー率74% (465/626)
関数名 (正確には関数指示子) は,sizeofなどの特定の演算子のオペランドとなる場合を除き,その関数へのポインタに変換されます。 そのためint_cmpと書いた場合は,int (*)(const int *, const *)型のポインタ値に変換されます。 →ISO/IEC 9899:1999 Programming languages - C / 6. Language / 6.3 Conversions / 6.3.2 Other operands / 6.3.2.1 Lvalues, arrays, and function designators / Paragraph 4 ただし,提示されたプログラムは未定義の振る舞いをします。 int_cmpは int int_cmp (const void *a, const void *b) { ... } という形式でなければいけません。 qsortの第4引数にキャストがあるのは,通常誤りです。 →ISO/IEC 9899:1999 / 7. Library / 7.20 General utilities <stdlib.h> / 7.20.5 Searching and sorting utilities / 7.20.5.2 The qsort function / Paragraph 3 および 6.3.2.3 Pointers / Paragraph 8
お礼
回答、ありがとうございます。int_cmpの関数を呼ぶのは、int (*)(const int *, const *)型のポインタ値に変換されることが判りましたが、int_cmp の位置が(const void *a, const void *b)の後にあるのは、何故でしょうか。
お礼
回答ありがとうございます。皆さんの回答のおかげで戻り値(int (*) ,引数(const void *, const vois *)の型でキャストしていることが 解りました。