Search code examples
csortingcomparisonquicksortqsort

without passing arguments how compare funcation work


I want to sort struct array but while understand the logic of compare function i stuck my confusion is how compare function is work when it call in qsort() function without passing argument

Using GCC on Code Block on windows:

Code

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

struct cricketers
{
  int avrun;
  char name[30];
  int age;
  int notm;
}india[Max] = {
  122, "Sachin Tendulkar", 30, 67,
  97, "Virendra Sehwag", 35, 56,
  66, "Irfan Pathan", 32, 45,
  153, "Yusuf Pathan", 36, 21,
  101, "Yuvaraj Singh", 32, 45,
};

int main()
{
  int i;
  qsort(india, 5, sizeof(struct cricketers), compare);

  for (i = 0; i < 5; i++)
  {
    printf("Name : %s", india[i].name);
    printf("\nAge : %d", india[i].age);
    printf("\nTotal Test Matches played : %d", india[i].notm);
    printf("\nAverage Run : %d\n\n\n", india[i].avrun);
  }
  _getch();
  return 0;
}

int compare(const void * a, const void * b)
{
  return (*(int*)a - *(int*)b);
}

Solution

  • It is the function qsort that internally calls the comparison function passing to it void pointers to two elements of the array.

    According to the C Standard (6.7.2.1 Structure and union specifiers) the address of the first member of a structure is equal to the address of the whole object of the structure type.

    15 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

    So the value for example of the parameter a casted to the type int * yields the address of the data member int avrun of the structure.

    Nevertheless this expression (*(int*)a - *(int*)b) can invoke undefined behavior due to overfloating of signed integers.

    I would write the comparison function the following way.

    int compare( const void *a, const void *b )
    {
        const struct cricketers *left  = ( const struct cricketers * )a;
        const struct cricketers *right = ( const struct cricketers * )b;
    
        return ( right->avrun < left->avrun ) - ( left->avrun < right->avrun ); 
    }