qsort_r()
и qsort_s()
В некоторых реализациях доступны функции с именем qsort_r()
или qsort_s()
, которые делают то, что вам нужно - взять указатель на дополнительные данные, которые передаются в функции компаратора.
Варианты реализации BSD (включая macOS или Mac OS X) предоставляют версию qsort_r()
, также как и библиотека GNU C.К сожалению, оба варианта имеют разные подписи.Это не мешает им быть полезными, но это означает, что один и тот же исходный код не может быть использован на двух платформах, и, кроме того, вы должны убедиться, что понимаете, какой вариант qsort_r()
доступен на любой машине, где вы пытаетесь
Аналогичным образом, Microsoft предоставляет версию qsort_s()
, а стандарт C11 определяет версию qsort_s()
(в качестве дополнительной функции в Приложении K, основанной на TR-24731), но эти дваразнятся в подписи снова.Возможно, к счастью, функции Приложения K не получили широкого распространения.
BSD qsort_r()
void qsort_r(void *base, size_t nel, size_t width, void *thunk,
int (*compar)(void *, const void *, const void *));
Библиотека GNU C qsort_r()
void qsort_r(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *),
void *arg);
Обратите внимание, чтов BSD 'thunk' эквивалентен 'arg' в GNU, но эти аргументы появляются в разных местах в последовательности вызова функции qsort_r()
(до и после указателя функции компаратора).Кроме того, обратите внимание, что «thunk» передается в качестве аргумента 1 в функции компаратора BSD, но «arg» передается в качестве аргумента 3 в функции компаратора GNU.
Мнемоника для qsort_r
: данные контекстауказывается в отношении компаратора в вызывающей последовательности в том же отношении, что и контекст, передаваемый компараторам в отношении двух сравниваемых значений.Контекст перед указателем на компаратор означает контекст перед значениями в вызове компаратора;контекст после указателя на компаратор означает контекст после значений в вызове компаратора.
Приложение K qsort_s()
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
int (*compar)(const void *x, const void *y, void *context),
void *context);
Приложение K qsort_s()
является уникальным по возврату значения;все остальные варианты не возвращают никакого значения.В противном случае для большинства практических целей он соответствует функции GNU qsort_r()
.
void qsort_s(void *base, size_t num, size_t width,
int (__cdecl *compare )(void *, const void *, const void *),
void * context);
Различия rsize_t
и size_t
не очень важно при сравнении вариантов приложения K и Microsoft qsort_s()
, но в приложении K qsort_s()
контекст передается в качестве аргумента 3 компаратору, а в Microsoft qsort_s()
контекст передается какаргумент 1 для компаратора.
Сводка
Функции, вызываемые qsort_r()
или qsort_s()
, обеспечивают необходимую функциональность.Однако вы должны проверить спецификацию платформы, для которой присутствует функция, и для правильной последовательности вызова для аргументов функции сортировки, и правильную последовательность вызова для аргументов для компараторов.
Номинально, вам также следует проверить тип возвращаемого значения функции, но немногие программы рассмотрят возможность его проверки, в основном потому, что большинство вариантов qsort()
не возвращают значения.