Understanding qsort() function

瘦欲@ 提交于 2019-12-12 06:27:08

问题


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

When I want to use qsort function, I should write a compare function in this form as I understood. So, why we are using void before the parameters of compare function?

And, is this compare function standard with its parameters and code in curly braces or can we simply change the code and even parameters through our wishes?


回答1:


No, you can not change the parameters or the return type. But of course you can change the 'code' of the function. You can compare whatever you want. The only important thing is the return value:

taken from here:

The return value should be <0 if the first passed parameter is 'lower' than the second, == 0 if both are identic or >0 if the first one is 'greater'.

For example you could use a qsort function with strings like this:

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



回答2:


In C void * means that you can store a pointer of any type in it. Imagine that you wanted to sort a list of strings(char *), what would you do? Write one implementation of qsort for int data type and one for char *? Here, qsort is written using void * to allow you to compare different stuff with different types.

Yes, the parameter type is standard. See the definition of it in stdlib.h.

void qsort(void *base, size_t nmemb, size_t size,
       int (*compar)(const void *, const void *));



回答3:


The reason why void pointers are used is because they can be cast into other pointer types and then back into void pointers without any issues.




回答4:


qsort is using a callback that allows you to use arbitrary datatypes and then inside the comparator you can sort them any way you please. You just need to adhere to the API.

This provides a lot of flexibility. The code below is a simplified example but it could have been extended to sort arbitrary data structures easily. In all cases the same qsort function is used ie the very same function at the same address is called.

The following contrived example might help to understand why it's flexible. Note, instead of int the comparator func_table could be extended to be a table of structures where each one has a comparator type. To reiterate, the same qsort function is called in each case, its the callback functions address that changes to the correct function required to sort the data at runtime.

The following program sorts an array in a random direction where the sort function is chosen from a table.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

int  values[] = {  3 , 88 , 52 , 285, 63 , 288 , 576 , 10, 21 , 5,343 , 38 , 55 , 100, 552 , 85 };

typedef int (*comparator)(const void * a, const void * b);

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

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

static comparator func_table[2];

int main(void) {
  srand(time(NULL));
  size_t int_arr_size = ARRAY_SIZE(values);
  int n = 0;
  int i = 0;
  func_table[0] = cmp_int;
  func_table[1] = cmp_reverse;
  while(i++ < 10) {
    int order = rand() % 2 == 0;
    printf("order: %d %s ", order, order == 0 ? ">" : "<");
    qsort(values, int_arr_size, sizeof(int), func_table[order]);
    for( n = 0 ; n < int_arr_size; n++ ) {   
      printf("%d ", values[n]);
    }
    printf("<\n");
  }
  return 0;
}


来源:https://stackoverflow.com/questions/37010074/understanding-qsort-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!