It's just a slight changes to your comparizon function to make library qsort stable. See link here
Something like below should do the trick (untested, be cautious):
int comp_on_price(const void *a, const void *b)
{
if ((*(B *)a).price < (*(B *)b).price)
return 1;
else if ((*(B *)a).price > (*(B *)b).price)
return -1;
else
// if zero order by addresses
return a-b;
}
This would work if you can guarantee a and b are in the same address space (two pointers in the same array) and that every comparisons give a greater overall ordering of the array, addresses of lower structures will tend to become even slower. This is true for bubble sorts or similar. That would also work for a trivial implementation of QucikSort (which qsort is not). However for other algorithms, or any algorithm using additional address space for temporary storage (maybe for optimization purpose), this property will not be true.
If what you sort contains any unique identifier in compared items (in the current example that is probably true for field ID), another method to make the sort stable would be to compare these items. You could also add such a unique key in a new field for that purpose, but as it uses more memory you should consider the third option described below before doing that.
My preferred method would still be a third one, do not directly sort an array of structures, but sort an array of pointers to actual structure items. This has several good properties. First you can compare arrays of the structure pointed to, as it won't change and it will make the sort stable.
The comparison function will become something like:
int comp_on_price(const void *a, const void *b)
{
if ((*(B **)a)->price < (*(B **)b)->price)
return 1;
else if ((*(B **)a)->price > (*(B **)b)->price)
return -1;
else
// if zero, order by addresses
return *(B **)a-*(B **)b;
}
Other good properties is that it avoid moving structures around while sorting, it only need moving pointers, and that can be time saving. You can also keep several such pointer arrays, and that allow several ordered accesses to array items at the same time.
Drawbacks are that it takes some memory and that access to items is slightly slower (one level of indirection more).