Charles Sullivan said:
Charles Sullivan wrote:
The library function 'qsort' is declared thus:
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
If in my code I write:
int cmp_fcn(...);
int (*fcmp)() = &cmp_fcn;
qsort(..., fcmp);
then everything works. But if instead I code qsort as:
qsort(..., &cmp_fcn);
the compiler complains about incompatible pointer type.
qsort is expecting a pointer to a function which returns an int and
gets passed two const void * parameters. However, you are passing
it a pointer to a function which returns int and gets passed a
variable number of unknown parameters.
No, he's not. A function that takes a variable number of arguments
must have at least one named argument before the "...". Note also his
use of "..." in the call to qsort. The ellipsis isn't being used as C
syntax; it's just an ellipsis.
He's just not showing us exactly what he's doing -- which means we
can't guess what the problem is.
Mea culpa. I had forgotten about the C syntax and used "..." to
represent stuff I _thought_ irrelevant to the question.
Here's an example which illustrates the way I've been using
qsort:
-------------------------------------
#include <stdio.h>
#include <stdlib.h>
int val[] = { 3, 2, 1, 4, 5 };
int cmp_fcn ( int *one, int *two )
{
return (*one < *two) ? -1 :
(*one > *two) ? 1 : 0;
}
int main ( void )
{
int (*fcmp)() = &cmp_fcn;
qsort((void *)val, 5, sizeof(int), fcmp);
printf("%d %d %d %d %d\n",
val[0], val[1], val[2], val[3], val[4]);
return 0;
}
-----------------------------------
Yup, the stuff you deleted was exactly what's relevant to the problem.
The "compar" argument to qsort must be a pointer to a function taking
two arguments of type "const void *" and returning a result of type
int. You're providing a pointer to a function taking two arguments of
type int* and returning a result of type int. The types are
incompatible.
You need to declare your cmp_fcn() function as:
int cmp_fcn(const void *one, const void *2);
Here's a modified version of your program:
#include <stdio.h>
#include <stdlib.h>
int val[] = { 3, 2, 1, 4, 5 };
int cmp_fcn ( const void *one, const void *two )
{
return (*(int*)one < *(int*)two) ? -1 :
(*(int*)one > *(int*)two) ? 1 : 0;
}
int main ( void )
{
qsort(val,
sizeof val / sizeof val[0],
sizeof val[0],
cmp_fcn);
printf("%d %d %d %d %d\n",
val[0], val[1], val[2], val[3], val[4]);
return 0;
}
Note that I've changed all four arguments to qsort().
For the first argument, I dropped the cast to void*. As long as
qsort's prototype is visible (which it is, since you have the
"#include <stdlib.h>", the conversion is done implicitly.
For the second argument, I compute the size of the val array rather
than assuming it's 5. This lets you change the size without having
to modify the call.
Similarly, the third argument is "sizeof val[0]" rather than
"sizeof(int)", allowing you to change the type of the array without
changing the qsort call (though you would have to change the
cmp_fcn function).
Finally, I pass the name of the function directly to qsort() rather
than storing it in a variable. The name of a function is implicitly
converted to a pointer-to-function in most contexts. (The exceptions
are the argument to sizeof, which makes "sizeof func" illegal rather
than yielding the size of a function pointer, and the argument to a
unary "&" operator, which makes &func nearly equivalent to func.)