sanyassh
sanyassh

Reputation: 8520

qsort on array of void*

So, I have a function to compare two const void* pointers, one pointer is bigger then other if it has bigger address

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

I have an array of void* and array[0] is bigger than array[1]

void* array[2];
void* a = malloc(10);
void* b = malloc(10);
if (func(a, b) < 0)
{
    array[0] = b;
    array[1] = a;
}
else
{
    array[0] = a;
    array[1] = b;
}
// for example, array contains 0x15cfeb0 and 0x15cfe90

And after that I'm doing qsort and the array doesn't change!

qsort(array, 2, sizeof(void*), (*func));
// array is 0x15cfeb0 and 0x15cfe90 instead of expected 0x15cfe90 and 0x15cfeb0  

What am I doing wrong?

Upvotes: 1

Views: 340

Answers (1)

Barmar
Barmar

Reputation: 781068

The arguments to the comparison function are pointers to the array elements, not the array elements themselves. So you need to compare what they point to.

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

BTW, what you're doing is not really well defined. The result of converting a pointer to an integer is implementation-dependent.

There can also be overflow when converting the result of subtracting long to int. It would be better to just test them for less than or greater than:

uintptr_t aval = (uintptr_t)(*(void **)a);
uintptr_t bval = (uintptr_t)(*(void **)b);
if (aval == bval) {
    return 0;
} else if (aval < bval) {
    return -1;
} else {
    return 1;
}

Upvotes: 5

Related Questions