Я пишу функцию, которая получает указатель на функцию сравнения и массив MyStructs
и должна сортировать массив в соответствии с функцией сравнения:
void myStructSort(
struct MyStruct *arr,
int size,
int (*comp)(const struct MyStruct *, const struct MyStruct *)) {
qsort(arr, size, sizeof(struct MyStruct), comp);
}
К сожалению, это не скомпилируется, потому что qsort
ожидает, что компаратор получит аргументы void *
, а не const struct MyStruct *
. Я подумал о нескольких плохих решениях и задался вопросом, что такое правильное решение.
Вариант 1
Вставить comp
в int (*)(const void *, const void*)
. Это компилируется, но это поведение undefined (см. этот вопрос SO).
Вариант 2
Создайте глобальную переменную int (*global_comp)(const struct MyStruct *, const struct MyStruct *)
и установите global_comp=comp
внутри myStructSort
. Затем создайте функцию:
int delegatingComp(const void *a, const void *b) {
return globalComp((const struct MyStruct *)a, (const struct MyStruct *)b);
}
И в myStructSort
вызовите qsort(arr, size, sizeof(struct MyStruct), delegatingComp)
. Проблема с этим - нечеткая глобальная переменная.
Вариант 3
Повторить qsort
. Это функционально безопасная, но очень плохая практика.
Есть ли волшебный идеальный четвертый вариант?
Edit
Я не могу изменить API myStructSort
, и я компилирую свой код с помощью gcc c99 -Wall -Wextra -Wvla
.