1
votes

This code snippet is mainly from man page of qsort.

int cmp(const void *p1, const void *p2)
{
   char s1 = *(*(char * const *)p1);
   char s2 = *(*(char * const *)p2);
   return s1 - s2;
}

int main(int argc, char *argv[])
{
  int j; 
  printf("Before Qsort: \n");
  for(j = 1; j <argc ; j++)
    printf("%s ", argv[j]);
  printf("\n");
  qsort(&argv[1], argc - 1, sizeof(char *), cmp);
  printf("After Qsort: \n");
  for(j = 1; j <argc ; j++)
    printf("%s ", argv[j]);
  printf("\n");
}

I can understand I pass the address of pointer to char array which is &argv[1] in the qsort However, I am confused why I have to do the following cast to get the value?

*(*(char * const *)p1)

I also checked other questions in stackoverflow, it is easy when we pass 1-D array. So, I can use

type var = *(const type *)p1 to get the value

Looking into this example, the type cast looks so weird to understand.

Would you please help me to understand the meaning of every piece cast to reach the final value?

Thanks.

1
The snippet compares only the first characters of the strings, is that what you want? The snipet does have *(type *)p1 in it, where type is const char*. - n. 1.8e9-where's-my-share m.
what I want to parse is the array from command line argument. - rickhau

1 Answers

2
votes

This:

char s1 = *(*(char * const *)p1);

Does two things:

  • Dereference (char * const *) p1, i.e. cast p1 to a pointer to a character pointer (let's ignore the const, and dereference that. That yields a character pointer.
  • Dereference that character pointer, yielding a single character.

The code for s2 is of course the same, but for p2.

The qsort() library function will call cmp() with p1 and p2 pointing into argv, which is not a "2D char array", it's a 1D array of character pointers. So qsort() will call cmp() with pointers pointing at those pointers, since it's the pointers that are being sorted.

The sorting is then (dangerously) done by subtracting only these first characters from each other. That part, the return, is better written:

return s1 < s2 ? -1 : s1 > s2;

As posted the code has integer underflow issues.