简体   繁体   中英

How does the compare function in qsort work?

I found this sample code online, which explains how the qsort function works. I could not understand what the compare function returns.

#include "stdlib.h"

int values[] = { 88, 56, 100, 2, 25 };

int cmpfunc (const void * a, const void * b) //what is it returning?
{
   return ( *(int*)a - *(int*)b ); //What is a and b?
}


int main(int argc, _TCHAR* argv[])
{

   int n;

   printf("Before sorting the list is: \n");
   for( n = 0 ; n < 5; n++ ) {
      printf("%d ", values[n]);
   }

   qsort(values, 5, sizeof(int), cmpfunc);

   printf("\nAfter sorting the list is: \n");
   for( n = 0 ; n < 5; n++ ) {
      printf("%d ", values[n]);
   }
    return 0;
}
int cmpfunc (const void * a, const void * b) //what is it returning?
{
   return ( *(int*)a - *(int*)b ); //What is a and b?
}

Is equivalent to:

int cmpfunc (const void * a, const void * b) //what is it returning?
{
   // qsort() passes in `void*` types because it can't know the actual types being sorted
   // convert those pointers to pointers to int and deref them to get the actual int values

   int val1 = *(int*)a;
   int val2 = *(int*)b;

   // qsort() expects the comparison function to return:
   // 
   //    a negative result if val1 < val2
   //    0 if val1 == val2
   //    a positive result if val1 > val2

   return ( val1 - val2 ); 
}

What a and b are is clearly stated in the documentation for qsort : these are pointers that point to array elements that have to be compared.

Comparison function in this case knows that the array elements are of type int . So it casts the void * pointers to int * type and performs a tri-state comparison of the pointed int values by subtracting the second from the first.

It will work properly for your set of values, but in general case using subtraction for tri-state comparison is a bad programming practice, since it is prone to overflow. Also, the function in your sample code unnecessarily casts away the constness of the pointed values.

A better alternative would be

int cmpfunc(const void *a, const void *b)
{
   const int *A = a, *B = b;
   return (*A > *B) - (*A < *B);
}

Whenever the sorting algorithm needs to find out which of two elements should be placed before the other, it will call the comparison function and pass pointers to the two elements. Since you are sorting int values, the pointers are actually pointers to int , but the signature must take void* so that it can be used with any data type. Therefore, in order to obtain the actual element value, a must be cast to int* and then be dereferenced - hence, *(int*)a . The function must return a negative value if a is to be placed before b , a positive value if b is to be placed before a , or zero if it doesn't matter which is placed first (which is usually the case when the elements are equal). In this particular case, since we are working with numbers, simply subtracting the value of b from the value of a is sufficient if we want the biggest numbers to go first.

From http://en.cppreference.com/w/cpp/algorithm/qsort

The cmp function returns ​a negative integer value if the first argument is less than the second, a positive integer value if the first argument is greater than the second and zero if the arguments are equal.

The function takes void pointers so the qsort function may be used with any data type. However inside the cmp function you must explicitly cast the pointer to the actual data type.

a and b are being compared as integers - they have to be passed in as void * but are then cast to int * before finally being deferenced. As for the return value, it will either be positive, negative, or zero, all of which would be taken into account in the sorting function.

qsort will give each pair it needs to compare to cmpfunc and uses it's return value to see which one is greater and then sorts the array accordingly.

Basically, if the compare function returns a positive result this means that the first argument is greater than the second one. Similarly, if it returns negative, then the second argument is greater.

In the example, we want to sort integers. So, we need to decide which one is greater when we compare two elements of the given array. To compare those, a simple substraction operation is enough since the result is positive when a is greater, 0 if a and b are equal and negative if b is greater.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM