Прежде чем заняться другими аспектами, вы переключили второй и третий параметры на qsort(3)
, первый - указатель массива, второй - число элементов, третий размер и четвертый - указатель функции сравнения.Чтобы получить хороший qsort(3)
, вам сначала нужно поместить параметры в правильном порядке :)
.
Ну, функция compare()
должна возвращать < 0
(не -1), если a
меньшечем b
, > 0
(а не +1), если a
больше, чем b
, и ноль, если a
и b
равны.Ваша формула правильная, но немного слишком сложное выражение для чего-то, что может быть достигнуто простым вычитанием обоих параметров.Если вы проверите, что возвращают многие реализации strcpy(3)
(ну, не все, но многие), это разница между символами в позиции, в которой обе строки различаются, что достаточно для эффективной реализации.
ByКстати, вы знаете, что void *
- это указатель, совместимый с любым другим типом указателя, поэтому один из лучших способов написать функцию сравнения (основанную на ссылках на целые числа, а не на их значениях) - написать ее так:
int compare(int *a, int *b)
{
return *a - *b;
}
int reverse_compare(int *a, int *b)
{
return -compare(a, b);
}
(вы получите ложное предупреждение при вызове qsort(3)
) или, что еще проще,
int reverse_compare(int *a, int *b)
{
return compare(b, a);
}
и передадите его непосредственно qsort(3)
.Действительно, для обратного сравнения требуются только два указателя, и его можно сделать полностью общим, написав его следующим образом:
int reverse_compare(const void *a, const void *b)
{
return compare(b, a);
}
pru.c
Если вы проверите следующий пример, выобратите внимание, что reverse
- это процедура, переданная в qsort
(нет предупреждений при совпадении параметров и нет предупреждений внутри тела reverse
при преобразовании их в void *
при вызове в compare_int
.)
#include <stdlib.h>
#include <stdio.h>
int compare_int(const int *a, const int *b)
{
return (*a > *b) - (*b > *a);
}
int reverse(const void *a, const void *b)
{
return compare_int(b, a);
}
int main()
{
int x[] = {500, 456, 18, 13, 3, 89, 800,
6874};
qsort(x,
sizeof(x)/sizeof(x[0]),
sizeof(x[0]),
reverse);
for (int i=0; i <
sizeof(x)/sizeof(x[0]); i++) {
printf("%d\n", x[i]);
}
return 0;
}