Это именно то, что делает приведенный вами актерский состав: он преобразует указатель типа
int (*)(const void **, const void **)
в указатель типа
int (*)(const void *, const void *)
Последнее - то, что ожидается от qsort
.
Подобные вещи встречаются довольно часто в коде плохого качества.Например, когда кто-то хочет отсортировать массив int
s, он часто пишет функцию сравнения, которая принимает указатели на int *
int compare_ints(const int *a, const int *b) {
return (*a > *b) - (*a < *b);
}
, и когда приходит время фактически вызвать qsort
, онипринудительно приведите его к нужному типу, чтобы подавить жалобы компилятора
qsort(array, n, sizeof *array, (int (*)(const void *,const void *)) compare_ints);
Это «взлом», который приводит к неопределенному поведению.Это, очевидно, плохая практика.То, что вы видите в своем примере, является просто менее прямой версией того же «хака».
В таких случаях правильным подходом было бы объявить функцию сравнения как
int compare_ints(const void *a, const void *b) {
int a = *(const int *) a;
int b = *(const int *) b;
return (a > b) - (a < b);
}
, а затемиспользуйте его без каких-либо приведений
qsort(array, n, sizeof *array, compare_ints);
В общем, если предполагается, что их функции сравнения будут использоваться в качестве компараторов в qsort
(и аналогичных функциях), следует реализовать их с параметрами const void *
.