Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does qsort() not have a return value?

Tags:

c

I'm a C++ programmer for the most part, but just for fun I was trying to do some generic programming in C. In particular, I implemented a generic sorting algorithm. The signature of my function is

int sort(void   *data,
         size_t num_elems,
         size_t elem_size,
         int    (*cmp)(const void*, const void*))

When I compared this to qsort() in the standard library, I noticed that unlike my function, qsort() does not have a return value. Since sorting an array will always require swapping elements, the implementation requires a temporary storage of size elem_size. As C doesn't have templates, elem_size is not known at compile time, so the temporary storage must be allocated dynamically, which could fail. In that case, qsort() couldn't sort the array, but it couldn't report the error either, so there is no way of knowing if the array is sorted upon return.

Am I missing something here?

like image 412
cthl Avatar asked Mar 08 '23 17:03

cthl


1 Answers

Any partitioning algorithm needs to be able to swap two elements, and the qsort API means that the code doesn't know how big they are at compile-time. But they don't need to be swapped as a whole; they can be swapped one byte at a time. (That's effectively what memcpy would do anyway.)

The following comment and macro are right at the beginning of qsort.c in the Gnu libc implementation. (Note that the code is subject to the LGPL)

/* Byte-wise swap two items of size SIZE. */
#define SWAP(a, b, size)                                                      \
  do                                                                          \
    {                                                                         \
      size_t __size = (size);                                                 \
      char *__a = (a), *__b = (b);                                            \
      do                                                                      \
        {                                                                     \
          char __tmp = *__a;                                                  \
          *__a++ = *__b;                                                      \
          *__b++ = __tmp;                                                     \
        } while (--__size > 0);                                               \
    } while (0)
like image 114
rici Avatar answered Mar 23 '23 04:03

rici