Although you can implicitly cast a char* to a void*, you can't do the same for a function pointer with those types (without a warning). The compiler is more careful with type matching on function signatures.
Not to mention that what's happening inside qsort would be the opposite: that is, a void* would be cast to a char* in numcmp and const char* in strcmp.
And the compiler should issue a warning in these cases. If you really have to use a function that doesn't have the same types as parameters, perhaps you should use a wrapper function that does match the types, and then does the appropriate explicit cast when calling the original function.
For instance:
static int strcmp_wrapper(void* s1, void* s2) {
return strcmp((char*)s1, (char*)s2);
}
static int numcmp_wrapper(void* n1, void* n2) {
return numcmp((char*)n1, (char*)n2);
}
qsort((void **) lineptr, 0, nlines-1,
(numeric ? numcmp_wrapper : strcmp_wrapper));
And the modern signature for qsort is
void
qsort(void *base, size_t nel, size_t width,
int (*compar)(const void *, const void *));
The issue of const
doesn't seem to come into play in your question, but K&R did not have const
.