3

I am rather new to C and I am reading this post: Killing Quicksort

and it says:

A note of caution for those playing along at home: the GNU C library qsort function is actually mergesort if the C library thinks the computer has enough free memory; to force quicksort, call the undeclared _quicksort function and compile with gcc -static.

Regarding the compiller option I use CMake and I have set the cmake flags to:

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -static")

but I am not sure how to call the undeclared _quicksort.

Does anyone have any experience with this?

Fix:

I have just declared the _quicksort function like @recycler suggested, in this manner:

void _quicksort(void *__base, size_t __nmemb, size_t __size,
        __compar_fn_t __compar);

and it seems to behave like a quicksort now. I am a beginner in C, and for me this seems like magic, but anyway, I consider myself satisfied for now.

Alex
  • 971
  • 1
  • 9
  • 23
  • I have put a breakpoint in my custom compar function and it does not seem to follow a quicksort algorithm. The two elements compared may be different on each breakpoint hit and I could not find the common pivot... – Alex Nov 28 '15 at 19:46
  • 1
    this is not magic. In order to use the function compiler needs to know its signature. The actual function is not looked up until the linking of the executable, where linked finds the function you referenced in the library and throws it into the final executable. For an unexposed internal function like this, the compiler won't find it (Since it is not in any header file you have included), but if you can get to the linking stage, linked will find that internal function just fine (as long as you are linking statically and there is no need to the function to be exposed from the shared library) – MK. Nov 28 '15 at 20:05
  • @MK seems I should start reading more about C basics. I am coming from Java and there encapsulation is done using access modifiers like public and private. In C, from what I know at this moment you can export implementations using header files. But this statically linking sounds to me like it is allowed for anyone to use everything from anywhere without restrictions :) – Alex Nov 28 '15 at 20:17
  • 2
    I looked at the glibc source code. It makes a _smart_ choice about when to do mergesort [which is _stable_ with guaranteed O(nlog(n))]. qsort is _unstable_ and can be worst case O(n^2). Static linking presents more problems than its worth, especially for a new C pgmr. I've been doing C for 30+ and I wouldn't waste time on this--just use glibc's function as is. You've got too much ground to cover with C. For a small primer, see my answer here: http://stackoverflow.com/questions/33661457/a-local-array-repeats-inside-a-loop-c – Craig Estey Nov 28 '15 at 20:44

2 Answers2

3

you could declare the function "_quicksort" in your c test code. This should be the same as qsort. Now you have to link it against the c-lib which should be done automatically by the linker. If the function _quicksort is exported, it can be used and the linker will link it to your binary. If it is not exported you get an error.

This is the quick and dirty option. You could also read the sources of the GNU C lib. Maybe there is another option.

recycler
  • 1,301
  • 9
  • 9
0

Just a heads up - your mileage may vary, but I just tested the glibc versions of _quicksort and mergesort at all different sizes and with arrays that were randomized, in order, and in anti-order. And mergesort was always about 25% faster than _quicksort. Which is probably why they replaced it. ;)

user2465201
  • 471
  • 5
  • 10
  • The default implementation of `qsort()` is an optimized sort in gcc. It isn't a `quicksort` or a `mergesort`, but rather a blend of both for efficiency. `qsort()` makes an intelligent choice of when to use what sort when. Essentially benefiting from quicksort when there are many partitions to sort and then switching to a mergesort (or insertion sort) as the number of partitions fall to roughly 16 or so. Forcing the use of one or the other playing with exported parts of `qsort()` loses the efficiencies built into it. – David C. Rankin Mar 31 '22 at 23:45