E
Eric Sosman
Lawrence said:A simple example is an insertion sort. A basic implementation
compares adjacent elements. If they are out of order it swaps them and
moves on. Essentially one element moves along the array until it is in its
correct place. An optimisation of this is to copy that element to a
temporary variable and compare that against array elements, move them when
out of order and finally write your temporary back to the free slot in the
array when you find the right position. Esssentially you can optimise a
lot of swap operations into moves. With the requirements of C99 the
element must stay in the array for the purposes of comparison so this
optimisation is no longer possible. You can "make do" but what is the
benefit of potentially cripping the efficiency of the qsort()
implementation?
Leave the "moving" item in place in the array until you
discover its destination, then swap it with its neigbors in
one operation. One of Jon Bentley's "Programming Pearls"
columns shows a neat way of doing this, or you could use
memcpy-memmove-memcpy via a temporary area (note that the
restriction applies only when the comparison function is
called; the use of non-array memory is permitted at other
times during the sort).
There's another consideration: How would qsort() acquire
sufficient temporary memory to hold a copy of an item of
arbitrary size? malloc() is unattractive because it can
fail but qsort() cannot. qsort() could, of course, be a
wrapper around two implementations, one for use when malloc()
succeeds and a fall-back to cope with failure -- but that
seems unattractive, since the dynamic memory doesn't seem to
add much to the overall efficiency.
[...]
Yes, that's the problem, C99 appears to have invented a pointless and
counterproductive restriction.
The restriction doesn't seem counter-productive, but I
admit I don't see much point in it. A comparison function
might, perhaps, modify the pointed-to elements (in a way
that doesn't affect the computed result, of course, and after
casting away the `const'-ness), and such modifications would
be problematic if two versions of "the same" element could
co-exist simultaneously. But why would a comparison function
want to do such a thing? I remain baffled.