I will get a little to the value of the string, but before I do this, let me get some basics of why qsort() needs its final parameter of the type it needs. qsort() is a function that can sort data of any type.
You provide it with
- a base pointer that points to the beginning of a continuous data block,
- the number of elements in the block,
- the size of one data item and
- A function that compares two data values.
Since the sorting algorithm is completely independent of the type of data being sorted, qsort() can be written without knowing which data types it sorts. But to do this, qsort() accepts void * parameters, which means a "generic pointer" in C.
Say you have an array of unsorted int values:
#define N 1024 int data[N] = { 10, 2, 3, -1, ... }
Then you can sort them by calling qsort() :
qsort(data, N, sizeof data[0], compare_int);
data is of type int * when passed to qsort() , and the first parameter qsort() is of type void * . Since any object pointer can be converted to void * in C, this is normal. The following two arguments are fine too. The final argument to compare_int must be a function that takes two parameters const void * and returns int . The function will be called qsort() with pairs of pointers from &data[0] to &data[N-1] as many times as needed.
To declare a function f() that "takes two parameters const void * and returns int ":
int f(const void *, const void *);
If you want to declare a pointer to a function that we can set to f , the pointer will be declared as:
int (*pf)(const void *, const void *); pf = f;
Brackets are necessary because otherwise pf will be a function returning int * . Now pf is a pointer to a function that returns an int .
Returning to our int sorting algorithm, and from the above, we can define compare_int() as:
int compare_int(const void *a, const void *b) { const int *the_a = a; const int *the_b = b; if (*the_a > *the_b) return 1; else if (*the_a < *the_b) return -1; else return 0; }
When writing compare_int() we know that the passed int * pointers are disguised as void * , so we convert them back to int * , which is fine, and then we compare the numbers.
Now we will turn our attention to this code:
static int compare_wid( TRELLIS_ATOM* a, TRELLIS_ATOM* b )
means compare_wid is a function that takes two TRELLIS_ATOM * parameters and returns int . As we just saw, the last argument to qsort() should be a function that is of type:
int (*)(const void *, const void *)
Ie, a function that takes two parameters const void * and returns int . Since the types do not match, the programmer distinguishes compare_wid() from the type required by qsort() .
However, this has problems. Function type:
int (*)(TRELLIS_ATOM *, TRELLIS_ATOM *)
not equivalent to a function like:
int (*)(const void *, const void *)
therefore, it will not be guaranteed if the throw works. It is much simpler, correct and standard to declare compare_wid() as follows:
static int compare_wid(const void *a, const void *b);
And the definition of compare_wid() should look like this:
static int compare_wid(const void *a, const void *b) { const TRELLIS_ATOM *the_a = a; const TRELLIS_ATOM *the_b = b; ... return x; }
If you do this, you wonβt need translation when you call qsort() , and your program will not only be easier to read, but also correct.
If you cannot change compare_wid() , then write another function:
static int compare_stub(const void *a, const void *b) { return compare_wid(a, b); }
and call qsort() with compare_stub() (without translation) instead of compare_wid() .
Edit: based on many incorrect answers, here is a test program:
$ cat qs.c #include <stdio.h> #include <stdlib.h> struct one_int { int num; }; #ifdef WRONG static int compare(const struct one_int *a, const struct one_int *b) { #else static int compare(const void *a_, const void *b_) { const struct one_int *a = a_; const struct one_int *b = b_; #endif if (a->num > b->num) return 1; else if (a->num < b->num) return -1; else return 0; } int main(void) { struct one_int data[] = { { 42 }, { 1 }, { 100 } }; size_t n = sizeof data / sizeof data[0]; qsort(data, n, sizeof data[0], compare); return 0; }
Compiling with compare() , defined as taking two values ββof const struct one_int * :
$ gcc -DWRONG -ansi -pedantic -W -Wall qs.c qs.c: In function `main': qs.c:32: warning: passing argument 4 of `qsort' from incompatible pointer type
Compilation with the correct definition:
$ gcc -ansi -pedantic -W -Wall qs.c $
Editing 2: There seems to be some confusion as to the legality of using compare_wid as-it-for the final qsort() argument. comp.lang.c FAQ, question 13.9 has a good explanation (my attention):
To understand why curious pointer conversions are needed in qsort comparison functions (and why casting a function pointer when calling qsort does not help), it is useful to think about how qsort works. qsort knows nothing about the type or presentation of sorted data: it just moves around small pieces of memory. (All he knows about pieces is their size, which you specify in qsort third argument.) To determine if two pieces need to be replaced, qsort calls the comparison function. (To swap, it uses the equivalent of memcpy .)
Since qsort is common with pieces of memory of an unknown type, it uses common pointers (void *) to refer to them. When qsort calls the comparison function, it passes as arguments two common pointers to the pieces to be compared. Since it passes common pointers, your comparison function should take general pointers and convert the pointers back to the appropriate type before manipulating them (for example, before doing the comparison). The void pointer is not the same type as the structure pointer, and on some machines it may have a different size or representation (which is why these casts are necessary for correctness).
As mentioned in the FAQ, also see this .