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);