Я пишу функцию, которая получает указатель на функцию сравнения и массив 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.