qsort
is working here, but if each member of array v
occupies sizeof(void *)
, why is qsort
expecting sizeof(int)
?
#include <stdio.h>
#include <stdlib.h>
int comp(const void *pa, const void *pb)
{
int a = *(int *)pa;
int b = *(int *)pb;
if (a > b)
return +1;
else
if (b > a)
return -1;
else
return 0;
}
int main(void)
{
int i, a[] = {3, 1, 2, 0, 4};
void **v;
v = malloc(sizeof(void *) * 5);
for (i = 0; i < 5; i++) {
v[i] = &a[i];
}
for (i = 0; i < 5; i++) {
printf("%d\n", *(int *)v[i]);
}
qsort(v[0], 5, sizeof(int), comp); // why sizeof(int) if v is void **
printf("Sorted:\n");
for (i = 0; i < 5; i++) {
printf("%d\n", *(int *)v[i]);
}
free(v);
return 0;
}
qsort(v[0], 5, sizeof(int), comp); // why sizeof(int) if v is void **
The address of the start of the memory block to be sorted that you pass to qsort
is
v[0] = &a[0]
the address of the initial element of a
, so the array that you sort is a
, not the block whose initial element v
points to. a
's elements are int
s, so sizeof(int)
is the correct size.
If you want to sort the array of pointers, you need to pass the address of the first element in that array, &v[0]
, or simply v
to qsort
. Then of course the size argument must be sizeof (void*)
:
qsort(v, 5, sizeof(void*), cmp);
but for that, you can't use the comparison function you have, you need
int cmp(const void *pa, const void *pb) {
int a = *(int*)(*(void**)pa);
int b = *(int*)(*(void**)pb);
if (a > b)
return +1;
else
if (b > a)
return -1;
else
return 0;
}
or something similar. Since what is passed to the comparison function from qsort
is the address of the things to compare, we need one indirection to get the pointers to compare, and since here we want to compare pointers by what int
values they point to, we need the second indirection to get the pointed-to int
s.