Bob said:
In K&R Chapter 5.11 about function pointers there is a line
qsort((void**) lineptr, 0, nlines-1, (int (*)(void*,void*))(numeric ?
numcmp : strcmp));
This is very odd indeed, assuming qsort() and strcmp()
are the Standard library functions and not some user-defined
functions with the same name (and static linkage). There are
at least four peculiarities:
- The first argument to qsort() should be a `void*', but
a `void**' is supplied instead. This may be all right
if <stdlib.h> has been included (see below, though), but
is risky and could fail on some machines, depending on
the actual type and value of `lineptr'.
- qsort() is being asked to sort an array of length zero.
That's not illegal, but it's weird.
- The fourth argument to qsort() should be of type
`int (*)(const void*,const void*)'. Since the cast
you've shown lacks the `const' qualifiers, the compiler
is required to protest if <stdlib.h> has been included.
- It is incorrect to use strcmp() as the fourth argument
to qsort(), even if you disguise its true type with a
cast. Since the array being sorted contains no elements
strcmp() will not be called and the error won't hurt,
but it's certainly odd to find strcmp() there.
Since Messrs. K and R are perfectly familiar with all the
above, I'm guessing that there must be additional context that
puts this peculiar line of code in a different light. Taken
in isolation, it just doesn't make sense. Not to me, anyhow.
Now qsort expects an array of pointers, two integers, and a function
with two pointer arguments.
Not quite. qsort() expects a `void*' pointer (what it
points to is usually an array of pointers, but need not be),
two `size_t' (not `int') arguments, and a pointer to an `int'-
valued function of two `const void*' arguments; there are also
requirements on how the pointed-to function must behave.
The third argument (a function with two pointer arguments) above is
s/third/fourth/
(int (*)(void*,void*)) (numeric ? numcmp : strcmp)
Say that numeric is 0 then it evaluates to
(int (*)(void*,void*)) (strcmp)
Now I would have expected something like
int (*strcmp) (void*,void*)
Are these two statements the same, and which rule in C says that they
are same?
The two are not the same. The first starts with a pointer
to the strcmp() function and converts it to a pointer to a
different type of function, namely, an `int'-valued function
of two `void*' arguments (note that strcmp() has different
argument types). The second could be a declaration of a pointer
variable named `strcmp', capable of pointing to `int'-values
functions of two `void*' arguments, but I don't see how the
second form could appear in an expression.