qsort_r()
はqsort()
のリエントラントバージョンで、追加の 'thunk'引数を受け取り、これをcompare関数に渡して、移植可能なCコードで使用できるようにしたいと考えています。 qsort()
はPOSIXであり、どこでもqsort_r()
はBSD拡張のようです。具体的な質問として、Windows Cランタイムにこれが存在するのか、それとも同等の機能がありますか? Windowsの場合qsortと比較して、re-entrant qsort_r関数はどのように移植可能ですか?
答えて
例で示したqsort_r/qsort_s(sort_rと呼ばれる)のポータブルバージョンを作成しようとしました。私はまた、Gitのリポジトリにこのコードを入れている(https://github.com/noporpoise/sort_r)
struct sort_r_data
{
void *arg;
int (*compar)(const void *a1, const void *a2, void *aarg);
};
int sort_r_arg_swap(void *s, const void *aa, const void *bb)
{
struct sort_r_data *ss = (struct sort_r_data*)s;
return (ss->compar)(aa, bb, ss->arg);
}
void sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *a1, const void *a2, void *aarg), void *arg)
{
#if (defined _GNU_SOURCE || defined __GNU__ || defined __linux__)
qsort_r(base, nel, width, compar, arg);
#elif (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \
defined __FREEBSD__ || defined __BSD__ || \
defined OpenBSD3_1 || defined OpenBSD3_9)
struct sort_r_data tmp;
tmp.arg = arg;
tmp.compar = compar;
qsort_r(base, nel, width, &tmp, &sort_r_arg_swap);
#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__)
struct sort_r_data tmp = {arg, compar};
qsort_s(*base, nel, width, &sort_r_arg_swap, &tmp);
#else
#error Cannot detect operating system
#endif
}
使用例:
#include <stdio.h>
/* comparison function to sort an array of int, inverting a given region
`arg` should be of type int[2], with the elements
representing the start and end of the region to invert (inclusive) */
int sort_r_cmp(const void *aa, const void *bb, void *arg)
{
const int *a = aa, *b = bb, *p = arg;
int cmp = *a - *b;
int inv_start = p[0], inv_end = p[1];
char norm = (*a < inv_start || *a > inv_end || *b < inv_start || *b > inv_end);
return norm ? cmp : -cmp;
}
int main()
{
/* sort 1..19, 30..20, 30..100 */
int arr[18] = {1, 5, 28, 4, 3, 2, 10, 20, 18, 25, 21, 29, 34, 35, 14, 100, 27, 19};
/* Region to invert: 20-30 (inclusive) */
int p[] = {20, 30};
sort_r(arr, 18, sizeof(int), sort_r_cmp, p);
int i;
for(i = 0; i < 18; i++) printf(" %i", arr[i]);
printf("\n");
}
コンパイル/実行/出力:私はMac上でテストしてみた
$ gcc -Wall -Wextra -pedantic -o sort_r sort_r.c
$ ./sort_r
1 2 3 4 5 10 14 18 19 29 28 27 25 21 20 34 35 100
Linux &間違いや改善を見つけた場合は、このコードを更新してください。このコードは自由に使用できます。
あなたがqsort_s
を使用します。http://msdn.microsoft.com/en-us/library/4xc60xas(VS.80).aspx
どうやらqsort_r
の互換性のないバージョンを持つBSDやGNUについてのいくつかの論争があるので、生産コードでそれを使用するには注意が:http://sourceware.org/ml/libc-alpha/2008-12/msg00003.html
ところで、_s
を「安全」を表し、_r
は「再入可能」を表しますが、両方とも追加のパラメータがあることを意味します。
ポータビリティ標準では指定されていません。また、それはqsort
の "スレッドセーフ"バージョンと呼ぶのは間違いだと思います。標準qsort
はスレッドセーフですが、qsort_r
は比較関数としてクロージャを渡すことができます。
明らかに、シングルスレッド環境では、グローバル変数とqsort
で同じ結果を得ることができますが、この使用法はスレッドセーフではありません。スレッドセーフに関する別のアプローチは、スレッド固有のデータを使用して、スレッド固有のデータ(pthread_getspecific
POSIXスレッド、またはgccの変数__thread
、今後のC1x標準)からパラメータを取得することです。
- 1. GLibはどのように移植可能ですか?
- 2. .NET文字列ハッシュ関数は移植可能ですか?
- 3. qsortとstd :: sortの比較
- 4. 関数は、qsortを使用しているときにintを比較する関数です。
- 5. Golangバイナリは移植可能ですか?
- 6. asciiテキストアートは移植可能ですか?
- 7. mod_wsgiと比較して、mod_pythonはどのように機能しますか?
- 8. 移植可能なCodeBlocks用のwxWidgetはどのようにしてビルドできますか?
- 9. 移植可能なEclipse
- 10. 移植可能なPHPデバッグ
- 11. 他のタイプと比較することは可能でしょうか?
- 12. 移植可能なEclipseとGoogleプラグイン
- 13. このJavaScriptコードを移植可能にするにはどうすればよいですか?
- 14. データベースとのデータの比較はどのようにですか?
- 15. あなたのモデルのデータベースをCakePHPでどのように移植可能にするのですか?
- 16. ARMのsssemblyで前のcmpと比較してbne分岐をどのように比較できますか?
- 17. Xcodeの比較機能はどのように使うのですか?
- 18. ワーカースレッドプールとジョブキューなどの移植可能なライブラリ
- 19. Python辞書キー(クラスオブジェクト)複数の比較関数との比較
- 20. QTとDelphiの可能性の比較
- 21. C#(.NET 2.0)アプリケーションを移植可能なアプリケーションとして展開するには?
- 22. Javaクラスが移植可能なSEクラスであるかどうかを確認
- 23. Scalaでは、ガベージコレクションに関して、不変で変更可能なセットとマップがどのように比較されますか?
- 24. GNU make%スタイルパターンルールの移植可能なファイル
- 25. イベントとオーバーライド可能なメソッドの比較
- 26. コンパイラが移植可能かどうかを移植可能に検出する方法<iostream> vs <iostream.h>
- 27. どのように移植性の高いC++ですか?
- 28. VB6で実行可能ファイルのサイズを比較するにはどうすればよいですか?
- 29. Formtasticとsimple_formはどのように比較されますか?
- 30. どのように仮想マシンをVMWareからVirtualBoxに移植しますか?
あなたはそうです。これはスレッドセーフではなく、リエントラントです。つまり、シングルスレッド環境でもそれが必要な場合があります。 – Gabe
'qsort'関数自体はリエントラントであるか、少なくともそれは正常な実装でなければなりません。問題は、引数リエントラントを必要とする比較関数を使って 'qsort'を呼び出す関数を作ることです。 –
もちろん、 'qsort'アルゴリズムはグローバルな状態を必要としないので、事実上リエントラントで、スレッドセーフです。私はちょうど 'qsort_r'が再入門が必要な場合に使用することを意図しているので、スレッドローカルストレージを使用しても必ずしも同じ結果が得られるわけではありません。 – Gabe