We can sort an array like the one above using either of these functions:
#include <stdlib.h>
void qsort(void *base,
           size_t nmemb,
           size_t size,
           int (*cmp)(const void *elem1,
                      const void *elem2));
          #define __STDC_WANT_ 1 #includeLIB_ EXT1__ <stdlib.h>errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size, int (*cmp)(const void *elem1, const void *elem2, void *ctxt), void *ctxt);
Both take the start of an array base, the number of elements in the array
          nmemb, the size of each element in
          the array size, and a pointer to a
          comparison function cmp. Like our
          compare_persons function, the
          comparison function is expected to take two pointers
          elem1 and elem2, and yield positive, negative or zero
          according to their relative ordering. Because of the
          differing parameter types, we cannot pass a pointer to
          compare_persons directly to these
          functions without rewriting it. An alternative is to
          write a wrapper with the correct types:
static int cmpper_for_qsort(const void *elem1, const void *elem2) { return compare_persons(elem1, elem2); } qsort(database, ENTRY_COUNT, sizeof database[0], &cmpper_for_qsort);
The wrapper for qsort_s
          is similar:
static int cmpper_for_qsort_s(const void *elem1, const void *elem2, void *ctxt) { return compare_persons(elem1, elem2); } qsort_s(database, ENTRY_COUNT, sizeof database[0], &cmpper_for_qsort_s, NULL);
The comparison function will only be invoked with
          elem1 and elem2 pointing to elements of the specified
          array. The final argument to qsort_s is
          passed unmodified as the third argument ctxt in every call to the comparison function,
          allowing user-defined context to be passed through
          without using static storage. In summary, we inject the
          behaviour defined by our comparison function into the
          sorting algorithm that qsort and
          qsort_s
          implement. Despite the name, there is no reason to
          believe that the algorithm is Quick
          Sort; the function may use any algorithm, and may
          even choose different algorithms based on, for example,
          the size of the array, the size of elements, etc.
qsort_s
          returns non-zero if nmemb or
          size exceed RSIZE_.
The sorting functions re-arrange elements by copying them byte-by-byte, which is possible because the size of each element is provided. To reduce copying, it might be appropriate to have a separate array of pointers to the structures, and sort the pointers:
const struct person *ptrs[ENTRY_COUNT] = { &database[0], &database[1], &database[2], ... }; static int cmpper_for_qsort(const void *elem1, const void *elem2) { const struct person *const *pp1 = elem1; const struct person *const *pp2 = elem2; return compare_persons(*pp1, *pp2); } qsort(ptrs, ENTRY_COUNT, sizeof ptrs[0], &cmpper_for_qsort);
This technique is also appropriate if you want to build multiple indices to the same array, or an index to something that isn't an array.
