6

I wrote my comparison function

int cmp(const int * a,const int * b)
 {
   if (*a==*b)
   return 0;
else
  if (*a < *b)
    return -1;
else
    return 1;
}

and i have my declaration

int cmp (const int * value1,const int * value2);

and I'm calling qsort in my program like so

qsort(currentCases,round,sizeof(int),cmp);

when i compile it I get the following warning

warning: passing argument 4 of ‘qsort’ from incompatible pointer type
/usr/include/stdlib.h:710: note: expected ‘__compar_fn_t’ but argument is of type ‘int
(*)(const int *, const int *)’

The program works just fine so my only concern is why it doesn't like the way im using that?

Matt Phillips
  • 11,249
  • 10
  • 46
  • 71

2 Answers2

20

The cmp function's prototype must be

int cmp(const void* a, const void* b);

You can either cast it in the invocation of qsort (not recommended):

qsort(currentCases, round, sizeof(int), (int(*)(const void*,const void*))cmp);

or casts the void-pointers to int-pointers in cmp (the standard approach):

int cmp(const void* pa, const void* pb) {
   int a = *(const int*)pa;
   int b = *(const int*)pb;
   ...
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 7
    Technically the first is undefined behavior. There is no guarantee that your implementation's calling convention passes a `const int*` the same way it passes a `const void*`. In practice, I expect it'll be fine. Apparently GCC expects that too since it's only a warning. – Steve Jessop Apr 01 '10 at 15:58
  • 2
    The approach with cast is completely unacceptable, even if it might seem to "work". – AnT stands with Russia Apr 01 '10 at 16:04
  • 2
    @AndreyT: What else do you suggest? Write your own quick sort? (Note that this is C, not C++, you cannot use `std::sort`.) – kennytm Apr 01 '10 at 16:08
  • @KennyTM: I think AndreyT meant the cast in the first approach in your answer, not the second. For the second, you can of course do `int *the_a = pa; int a = *the_a;` etc., which doesn't use a cast. – Alok Singhal Apr 01 '10 at 16:20
  • @KennyTM: What I suggest is using the cast on the parameters, as you did in your second suggection. This is the only way to do it. – AnT stands with Russia Apr 01 '10 at 16:29
  • @AndreyT: I see. Because both methods involve casting ^_^. – kennytm Apr 01 '10 at 17:33
  • Long story short: Casting function pointer types = evil, casting other types = less evil – Kos Dec 17 '12 at 07:58
0

According to the man page, a __compar_fn_t is defined as: typedef int(*) __compar_fn_t (const void *, const void *)

Your cmp specifies int* parameters. It doesn't like that, but is only listed as a warning.

KevenK
  • 2,975
  • 3
  • 26
  • 33
  • Thats because void* can be implicitly cast to any other type of pointer. in C at least, C++ has some issues with it. – Aatch Dec 24 '10 at 10:36
  • Which man page are you looking at? The one for `qsort` does not mention `__compar_fn_t` – Flimm Sep 24 '14 at 15:33