The problem is with the type cast operator in the the compare function comfunc
.
int cmpfunc(const void *a, const void *b) {
// error. casting to int * instead of char *
return *(int*)a - *(int*)b;
}
Casting the void pointer a
to int *
and then dereferencing it means it will read the sizeof(int)
bytes from the start of the address contained in a
. So the expression in the return statement is comparing the sizeof(int)
number of bytes from the address in a
with the sizeof(int)
number of bytes from the address in b
, instead of comparing the characters at the addresses contained in the pointers a
and b
. To illustrate this, I changed the compare function to
int cmpfunc(const void *a, const void *b) {
printf("comparing %c and %c\n", *((char *)a), *((char *)b));
printf("compare as int %d - %d = %d\n", *(int *)a, *(int *)b, *(int *)a - *(int *)b);
printf("compare as char %d - %d = %d\n", *(char *)a, *(char *)b, *(char *)a - *(char *)b);
return *(char *)a - *(char *)b;
}
And this is the output I get
comparing b and c
compare as int 1634034530 - 1684104547 = -50070017
compare as char 98 - 99 = -1
comparing a and d
compare as int 25697 - 100 = 25597
compare as char 97 - 100 = -3
comparing e and a
compare as int 6578533 - 25697 = 6552836
You can see the difference in the values read when comparison is done after typecasting to int *
, and after typecasting to char *
. The compare function should be changed to
int cmpfunc(const void *a, const void *b) {
// typecast the void pointers to correct type
return *(char *)a - *(char *)b;
}
Also, you don't need to cast the result of strlen
function and sizeof
operator as they already return values of type size_t
. Also, it is more readable and maintainable to use sizeof
on the array element. You should simply call qsort
as
qsort(str, strlen(str), sizeof str[0], cmpfunc);
str1
is initialized with"bcead\0"
and has size 6. It is not in "immutable ram". Right about theint
part. – Troubadour