Reputation: 1324
So I have a C function that goes like this:
int cmp (const void *a, const void* b)
return rot13cmp( (const char*)a, (const char*)b );
}
and rot13cmp is another function that takes two parameters of type const char *.
I pass this function into the compare parameter for the C qsort function but it doesn't seem to work.
However, if I instead cast the const void * variables by doing
return rot13cmp ( *(const char **)a, *(const char **)b );
the function then starts to work. I looked this up at SO but every source said that the first method of casting should work so I wanted to know why only the second one worked for me?
Edit: Here's the relevant code I have,
int cmp (const void *a, const void *b) {
return rot13cmp( (const char *)a, (const char *)b );
}
int rot13cmp (const char *a, const char *b) {
while (*a == *b && *a != '\n') {
a++;
b++;
}
if (*a == *b) { return 0; }
else if (*a == '\n') { return 1; }
else if (*b == '\n') { return 1; }
else { return rot13(*a) - rot13(*b);
}
and rot13 returns an int for the ASCII code of a letter rotated by 13 letters in the alphabet.
I called qsort by doing
qsort(words, word_count, sizeof(char*), cmp);
where words is an array of char** and word_count is an int. cmp is also just
Upvotes: 1
Views: 6460
Reputation: 229603
qsort()
calls the comparison function with pointers to the array elements that should be compared.
If your array contains const char*
, that means the comparison function is called with pointers to those pointers, and you have to cast and dereference accordingly.
With (const char*)a
you are interpreting the parameter as if it would be a pointer to const char
. But it isn't. In reality it's a pointer to the const char*
in the input array.
That's why (const char**)a
is the correct cast, it interprets the parameter as a pointer to a const char*
. To do string comparison you want that pointed-to const char*
, which you access by dereferencing the casted value with *
.
You can think of it as first correcting the type (by casting), and then accessing the pointed-to value (by dereferencing).
The difference between the two attempts is that the second case does an additional dereference. This is important since qsort()
doesn't pass the const char*
directly, but rather passes a pointer to it. So we have to look at the pointed-to value to find what we are looking for. By casting directly to const char*
we just claim that the variable would contain such a pointer, which won't end well because that's not the case.
Upvotes: 5