Если вы посмотрите на фактический вызов qsort
...
qsort((void*)table, tableSize, sizeof table[0], sortFunction);
... вы увидите, что это обеспечивает:
- a
void*
адрес и размер (в байтах) всего массива данных для сортировки, затем
- размер одного элемента данных в этом массиве, тогда
- указатель на функцию сравнения «sortFunction».
Не передан аргумент, который позволяет qsort
знать, что такое тип элемента - т.е. как отдельные биты в любом отдельном элементе данных используются для представления некоторого значения данных - так что нет никакого способа qsort
может значимо сравнить два таких элемента. Когда вы поставляете ...
int sortFunction(const void *a, const void *b)
{
int intOne = *((int*)a);
int intTwo = *((int*)b);
... и qsort
вызывает это, вы получаете два указателя - они обращаются к адресам памяти, но когда qsort
вызывает sortFunction
, эти void
указатели все еще ничего не сообщают об элементе данных напечатайте , поскольку qsort
не имеет никакой проницательности. Последние две строки кода выше, где вы - программист, координирующий вызов qsort
, - повторно применяете знания, которые у вас были все время о том, каков тип элемента данных: в данном случае это int
s, поэтому вы преобразуете каждый void*
в int*
(используя (int*)a
), а затем разыменовываете значение int*
, чтобы получить int
по адресу памяти a
. Аналогично для b
. При этом вы восстановили два числа, которые были там , как числа . Затем задание sortFunction
состоит в том, чтобы указать, как они должны быть упорядочены после завершения сортировки. Чтобы указать, что a
должно быть первым, sortFunction
может вернуть любое отрицательное значение (например, -1
); если они эквивалентны, return 0;
, и если b
должно быть первым, вернуть любое положительное значение (например, 1
). qsort()
получает эту информацию и использует ее, чтобы понять, как перемешивать элементы данных при сортировке.
FWIW, C позволяет вам выразить это более кратко, как ...
return intOne < intTwo ? -1 :
intOne == intTwo ? 0 :
1;
... или (быстрее, но полагаясь на логические результаты сравнения равные 0 и 1, что может запутать некоторых программистов, читающих ваш код) ...
return (intOne > intTwo) - (intOne < intTwo);
... или, если вы уверены , следующее никогда не может быть математически меньше INT_MIN
(такие значения неуместно переносятся в большое положительное число) ...
return intOne - intTwo;