Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to qsort an array of pointers to char in C?

Suppose I have an array of pointers to char in C:

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" }; 

And I wish to sort this array using qsort:

qsort(data, 5, sizeof(char *), compare_function); 

I am unable to come up with the compare function. For some reason this doesn't work:

int compare_function(const void *name1, const void *name2) {     const char *name1_ = (const char *)name1;     const char *name2_ = (const char *)name2;     return strcmp(name1_, name2_); } 

I did a lot of searching and found that I had to use ** inside of qsort:

int compare_function(const void *name1, const void *name2) {     const char *name1_ = *(const char **)name1;     const char *name2_ = *(const char **)name2;     return strcmp(name1_, name2_); } 

And this works.

Can anyone explain the use of *(const char **)name1 in this function? I don't understand it at all. Why the double pointer? Why didn't my original function work?

Thanks, Boda Cydo.

like image 295
bodacydo Avatar asked Aug 15 '10 20:08

bodacydo


People also ask

What does qsort do in C?

The qsort() function sorts an array of num elements, each of width bytes in size, where the first element of the array is pointed to by base. The compare pointer points to a function, which you supply, that compares two array elements and returns an integer value specifying their relationship.

How do you sort an array of pointers?

Approach: The array can be fetched with the help of pointers with the pointer variable pointing to the base address of the array. Hence in order to sort the array using pointers, we need to access the elements of the array using (pointer + index) format.

How do you qsort a string?

To use qsort with array of strings, we need to customize the compare function. This can be done using strcmp function to compare strings in C. Note strings are array of characters in C.


2 Answers

If it helps keep things straight in your head, the type that you should cast the pointers to in your comparator is the same as the original type of the data pointer you pass into qsort (that the qsort docs call base). But for qsort to be generic, it just handles everything as void*, regardless of what it "really" is.

So, if you're sorting an array of ints, then you will pass in an int* (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to int*, and dereference to get the int values that you actually compare.

Now replace int with char*:

if you're sorting an array of char*, then you will pass in a char** (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to char**, and dereference to get the char* values you actually compare.

In your example, because you're using an array, the char** that you pass in is the result of the array of char* "decaying" to a pointer to its first element. Since the first element is a char*, a pointer to it is a char**.

like image 102
Steve Jessop Avatar answered Sep 24 '22 20:09

Steve Jessop


Imagine your data was double data[5] .

Your compare method would receive pointers (double*, passed as void*) to the elements (double).
Now replace double with char* again.

like image 38
Henk Holterman Avatar answered Sep 22 '22 20:09

Henk Holterman