A Question About Function Pointer In C - c

There's the following declarations:
void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));
int numcmp(char *, char *);
int strcmp(char *s, char *t);
Then, somewhere in the program there is the following call:
qsort((void**) lineptr, 0, nlines-1,
(int (*)(void*,void*))(numeric ? numcmp : strcmp));
(Ignore the first three arguments and numeric).
I ask what is this:
(int (*)(void*,void*))(numeric ? numcmp : strcmp)
I understand that qsort is expecting a "pointer to function that gets two void pointers and returns an int" as it's 4th argument but how what's written above satisfies that?
It seems to me like some sort of cast because it is made of two parentheses, but that would be a very odd cast. Because it takes a function and makes this function a "pointer to function that gets two void pointers and returns an int". Which is meaningless.
(I followed here the rule that a type type in parenthesis before a variable promotes the variable to that type).
So I think I just get it wrong, maybe someone can tell me how to read this, what's the order?

What's happening here is indeed a cast. Lets ignore the ternary for a second and pretend that numcmp is always used. For the purpose of this question, functions can act as function pointers in C. So if you look at the type of numeric it is actually
(int (*)(int*,int*))
In order for this to be properly used in qsort it needs to have void parameters. Because the types here all have the same size with respect to parameters and return types, it's possible to substitute on for the other. All that's needed is a cast to make the compiler happy.
(int (*)(void*,void*))(numcmp )

You've missed the trick here - the portion
(numeric ? numcmp : strcmp)
is using the ternary operator to choose which function is being called inside of qsort. If the data is numeric, it uses numcmp. If not, it uses strcmp. A more readable implementation would look like this:
int (*comparison_function)(void*,void*) =
(int (*)(void*,void*))(numeric ? numcmp : strcmp);
qsort((void**) lineptr, 0, nlines-1, comparison_function);

As others have pointed out, for
(int (*)(void*,void*))(numeric ? numcmp : strcmp)
then the following is a type cast
(int (*)(void*,void*))
and the expression is
(numeric ? numcmp : strcmp)
C declarations can be quite difficult to read, but it is possible to learn. The method is to start at the inner part and then go right one step, then left one step, continuing right, left, right, left, etc outwards until finished. You do not cross outside a parenthesis before everything inside has been evaluated. For instance for the type cast above, (*) indicates this is a pointer. Pointer was the only thing inside the parenthesis so then we evaluate to the right side outside it. (void*,void*) indicates that is a pointer to a function with two pointer arguments. Finally int indicates the return type of the function. The outer parenthesis makes this a type cast.
Update: two more detailed articles: The Clockwise/Spiral Rule and Reading C Declarations: A Guide for the Mystified.
However, the good news is that although the above is extremely useful to know, there is an extremely simple way to cheat: the cdecl program can convert from C to English description and vice versa:
cdecl> explain (int (*)(void*,void*))
cast unknown_name into pointer to function (pointer to void, pointer to void) returning int
cdecl> declare my_var as array 5 of pointer to int
int *my_var[5]
cdecl>
Exercise: What kind of variable is i?
int *(*(*i)[])(int *)
Answer in rot13 in case you do not have cdecl installed on your machine (but you really should!):
pqrpy> rkcynva vag *(*(*v)[])(vag *)
qrpyner v nf cbvagre gb neenl bs cbvagre gb shapgvba (cbvagre gb vag) ergheavat cbvagre gb vag
pqrpy>

You can do it without the function pointer cast. Here's how. In my experience, in most places, if you are using a cast, you are doing it wrong.

Note that the standard definition of qsort() includes const:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Note that the string comparator is given two 'char **' values, not 'char *' values.
I write my comparators so that casts are unnecessary in the calling code:
#include <stdlib.h> /* qsort() */
#include <string.h> /* strcmp() */
int num_cmp(const void *v1, const void *v2)
{
int i1 = *(const int *)v1;
int i2 = *(const int *)v2;
if (i1 < i2)
return -1;
else if (i1 > i2)
return +1;
else
return 0;
}
int str_cmp(const void *v1, const void *v2)
{
const char *s1 = *(const char **)v1;
const char *s2 = *(const char **)v2;
return(strcmp(s1, s2));
}
Forcing people to write casts in the code using your functions is ugly. Don't.
The two functions I wrote match the function prototype required by the standard qsort(). The name of a function when not followed by parentheses is equivalent to a pointer to the function.
You will find in older code, or code written by those who were brought up on older compilers, that pointers to functions are used using the notation:
result = (*pointer_to_function)(arg1, arg2, ...);
In modern style, that is written:
result = pointer_to_function(arg1, arg2, ...);
Personally, I find the explicit dereference clearer, but not everyone agrees.

Whoever wrote that code snippet was trying to be too clever. In his mind, he probably thinks he is being a good programmer by making a clever "one-liner". In reality, he is making code that is less readable and is obnoxious to work with over the long term and should be rewritten in a more obvious form similar to Harper Shelby's code.
Remember the adage from Brian Kernighan:
Debugging is twice as hard as writing
the code in the first place.
Therefore, if you write the code as
cleverly as possible, you are, by
definition, not smart enough to debug
it.
I do lots of performance critical coding with hard real time deadlines... and I have still not seen a place where a dense one-liner is appropriate.
I have even messed around with compiling and checking the asm to see if the one-liner has a better compiled asm implementation but have never found the one-liner to be worth it.

I would probably read it like this:
typedef int (*PFNCMP)(void *, void *);
PFNCMP comparison_function;
if (numeric)
{
comparison_function = numcmp;
}
else
{
comparison_function = strcmp;
}
qsort((void**) lineptr, 0, nlines-1, comparison_function);
The example in the question has an explicit case.

Your logic is correct i think. It is indeed casting to "pointer to function that gets two void pointers and returns an int" which is the required type by the method signature.

Both numcmp and strcmp are pointers to functions which take two char* as parameters and returns an int. The qsort routine expects a pointer to a function that takes two void* as parameters and returns an int. Hence the cast. This is safe, since void* acts as a generic pointer. Now, on to reading the declaration: Let's take your strcmp's declaration:
int strcmp(char *, char *);
The compiler reads it as strcmp is actually:
int (strcmp)(char *, char *)
a function (decaying to a pointer to a function in most cases) which takes two char * arguments. The type of the pointer strcmp is therefore:
int (*)(char *, char *)
Hence, when you need to cast another function to be compatible to strcmp you'd use the above as the type to cast to.
Similarly, since qsort's comparator argument takes two void *s and thus the odd cast!

Related

How does "Pointer to Function" Syntax Work in C?

How (*ptr_fun1)(10) and ptr_fun1(10) are same in the below code
Code:
#include<stdio.h>
void fun1(int a)
{
printf("It is %d\n",a);
}
int main()
{
void (*ptr_fun1)(int);
ptr_fun1 = fun1;
/*
ex-
ptr_fun1 fun1
+----+ +-----+
+1000+ +code +
+----+ +-----+
1234 1000
fun1(10); <=> ptr_fun1(10); //how
*/
printf("%d\n%d",ptr_fun1(10),(*ptr_fun1)(20));
return 0;
}
output
10
20
Can some one please explain how it works.
The syntax for declaring (and using) function pointers in C (and C++) is one of the most puzzling aspects of the language for beginners. I shall try to explain a little, here.
First, let's consider pointers to 'simple' types (we'll take the 'int' type as an example). In this case, declaring a variable of the type is trivial: int N; Also, declaring a pointer to an int is also trivial: int *pN;We can interpret this second declaration in terms of 'evaluating' the '*' operator, which means "get the object that resides at the given address." So, in int *pN we are declaring that "the object that lies at the address "pN" is an int.
For functions, this is not so simple! Take a case of a function that takes an int as its (only) argument and returns an int value: int IFunc(int arg);. This is also very straightforward.
But how could we declare a pointer to such a function? We cannot simply apply the same logic as for the 'simple' types (by preceding with a * operator), like this:
int *pIFunc(int arg);
Because this would declare a function that takes an int arg and returns a pointer to an int.
So, the early implementors of the C language had to come up with something better - and completely unambiguous. So they decided to use the syntax of putting the "*NAME" section in parentheses, to isolate that 'dereference' operation from the function's definition:
int (*pIFunc)(int arg);
So, when faced with anything that looks remotely like this: < typename > (*Name1)(...); (where < typename > is any allowable C-type, like int, void, double, or even 'compound' types such as int*, and the "..." inside the second set of brackets can be either empty or a list of other 'types'), recognize it as a declaration of a function pointer (or as dereferencing a function pointer). To get the underlying function 'signature' (or invocation), just remove the first set of brackets and the contained *. So, for:
(*ptr_fun1)(20)
you can read:
ptr_fun1(20)
And, for:
void (*ptr_fun1)(int);
you can see that ptr_fun has the following signature:
void ptr_fun1(int);
I hope this makes things a bit clearer. Feel free to ask for further clarification and/or explanations.

Why can't I cast a function pointer to (void *)?

I have a function that takes a string, an array of strings, and an array of pointers, and looks for the string in the array of strings, and returns the corresponding pointer from the array of pointers. Since I use this for several different things, the pointer array is declared as an array of (void *), and the caller should know what kind of pointers are actually there (and hence what kind of a pointer it gets back as the return value).
When I pass in an array of function pointers, however, I get a warning when I compile with -Wpedantic:
clang:
test.c:40:8: warning: assigning to 'voidfunc' (aka 'void (*)(void)') from 'void *' converts
between void pointer and function pointer [-Wpedantic]
gcc:
test.c:40:8: warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
fptr = find_ptr("quux", name_list, (void **)ptr_list,
Here's a test file, which despite the warning does correctly print "quux":
#include <stdio.h>
#include <string.h>
void foo(void)
{
puts("foo");
}
void bar(void)
{
puts("bar");
}
void quux(void)
{
puts("quux");
}
typedef void (* voidfunc)(void);
voidfunc ptr_list[] = {foo, bar, quux};
char *name_list[] = {"foo", "bar", "quux"};
void *find_ptr(char *name, char *names[], void *ptrs[], int length)
{
int i;
for (i = 0; i < length; i++) {
if (strcmp(name, names[i]) == 0) {
return ptrs[i];
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = find_ptr("quux", name_list, (void **)ptr_list,
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
Is there any way to fix the warning, other than not compiling with -Wpedantic, or duplicating my find_ptr function, once for function pointers and once for non-function pointers? Is there a better way to achieve what I'm trying to do?
You can't fix the warning. In fact, in my opinion it should be a hard error since it's illegal to cast function pointers to other pointers because there are architectures out there today where this isn't just a violation of the C standard but an actual error that will make the code not work. Compilers allow it because many architectures get away with it even though those programs will crash badly on some other architectures. But it's not just a theoretical standard violation, it's something that causes real bugs.
For example on ia64 function pointers are (or at least used to be last time I looked) actually two values, both necessary to make function calls across shared libraries or a program and a shared library. Likewise, the common practice to cast and call function pointers to functions returning a value to a pointer to a function returning void because you know you'll ignore the return value anyway is also illegal on ia64 because that can lead to trap values leaking into registers causing crashes in some unrelated piece of code many instructions later.
Don't cast function pointers. Always have them match types. This is not just standards pedantry, it's an important best practice.
One solution is to add a level of indirection. This helps with lots of things. Instead of storing a pointer to a function, store a pointer to a struct storing a pointer to a function.
typedef struct
{
void (*ptr)(void);
} Func;
Func vf = { voidfunc };
ptrlist[123] = &vf;
etc.
This is something that has long been broken in the C standard and has never been fixed -- there is no generic pointer type that can be used for pointers to functions and pointers to data.
Before the C89 standard, all C compilers allowed converting between pointers of different types, and char * was generally used as a generic pointer that might point to any data type or any function. C89 added void *, but put in a clause that only object pointers could be converted to void *, without ever defining what an object is. The POSIX standard fixes this issue by mandating that void * and function pointers are safely convertable back and forth. So much code exists that converts function pointers to void * and expects it to work properly. As a result, pretty much all C compilers still allow it, and still generate the correct code, as any compiler that did not would be rejected as unusable.
Strictly speaking, if you want to have a generic pointer in C, you need to define a union that can hold either a void * or a void (*)() and use an explicit cast of the function pointer to the correct function pointer type before calling it.
The language lawyering reason is "because C standard does not explicitly allow it." C11 6.3.2.3p1/p8
1. A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a
pointer to void and back again; the result shall compare equal to the
original pointer.
8. A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall
compare equal to the original pointer. If a converted pointer is used
to call a function whose type is not compatible with the referenced
type, the behavior is undefined.
Notice that a function is not an object in C terminology, hence there is nothing that allows you to convert a pointer to a function to a pointer to void, hence the behaviour is undefined.
Castability to void * is a common extension though. C11 J.5 Common extensions 7:
J.5.7 Function pointer casts
1. A pointer to an object or to void may be cast to a pointer to a function, allowing data to be invoked as a function (6.5.4).
2. A pointer to a function may be cast to a pointer to an object or to void, allowing a function to be inspected or modified (for example, by a debugger) (6.5.4).
This is required by for example POSIX - POSIX has a function dlsym that returns void * but in fact it returns either a pointer to a function or a pointer to an object, depending of the type of the symbol resolved.
As to why this happens - nothing in C standard is undefined or unspecified if the implementations could agree on it. However there were and are platforms where the assumption that a void pointer and function pointer would be of the same width would really make things difficult. One of these is the 8086 16-bit real mode.
And what to use instead then? You can still cast any function pointer to another function pointer, so you can use a generic function pointer void (*)(void) everywhere. If you need both void * and a function pointer, you must use a struct or union or allocate void * to point to the function pointer, or ensure that your code only runs on platforms where J.5.7 is implemented ;)
void (*)() is recommended by some sources too, but right now it seems to trigger a warning in latest GCCs because it doesn't have a prototype.
With some modification you can avoid pointer conversations:
#include <stdio.h>
#include <string.h>
void foo(void)
{
puts("foo");
}
void bar(void)
{
puts("bar");
}
void quux(void)
{
puts("quux");
}
typedef void (* voidfunc)(void);
voidfunc ptr_list[] = {foo, bar, quux};
char *name_list[] = {"foo", "bar", "quux"};
voidfunc find_ptr(char *name, char *names[], voidfunc ptrs[], int length)
{
int i;
for (i = 0; i < length; i++) {
if (strcmp(name, names[i]) == 0) {
return ptrs[i];
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = find_ptr("quux", name_list, ptr_list,
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
As pointed out in other answers you shouldn't be allowed to assign a function pointer to an object pointer such as a void*. But you can safely assign a function pointer to any function pointer. Use reinterpret_cast in C++.
Let me give an example:
typedef void(*pFun)(void);
double increase(double a){return a+1.0;}
pFun ptrToFunc = reinterpret_cast<void(*)(void)>(increase);
the plain
pFun ptrToFunc = increase;
doesn't compile on several compilers.
I'm answering this old question because it seems that one possible solution is missing from existing answers.
The reason why the compiler forbids the conversion is that sizeof(void(*)(void)) can be different than sizeof(void*). We can make the function more generic, so that it can handle entries of any size:
void *find_item(char *name, char *names[], void *items, int item_size, int item_count)
{
int i;
for (i = 0; i < item_count; i++) {
if (strcmp(name, names[i]) == 0) {
return (char*)items + i * item_size;
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = *(voidfunc*)find_item("quux", name_list, ptr_list,
sizeof(ptr_list[0]),
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
Now the find_entry() function doesn't need to directly handle the item at all. Instead it just returns a pointer to the array, and the caller can cast it to a pointer-to-funcpointer before dereferencing it.
(The code snippet above assumes the definitions from original question. You can see full code also here: try it online!)

In C, does * also mean the same thing as void when used as a function argument?

For example, look at the following (abstract) declaration :
int (*) (*)
// pointer to a function returning an int and taking no arguments
(which I got from the following site : http://www.vineetgupta.com/blog/deciphering-complex-c-declarations)
I thought that only void means no arguments. Does this really mean the same thing as :
int (*) (void)
If so, where does it state that * can be used to specify no arguments?
Also, am I correct in assuming that abstract declarations such as this only exist for type casting? If so then it must be invalid in its current form since it lacks the surrounding parenthesis right? So int(*)(void) is invalid, but (int(*)(void)) is valid, no?
pointer to a function returning an int and taking no arguments
That's not right - the function takes a pointer as its argument, but since the type specifier is missing, the base type of the pointer is assumed to be int. This is ancient (pre-standard) behavior, some compilers allow it, others don't.
I thought that only void means no arguments. Does this really mean the same thing as :
int (*) (void)
No, it doesn't, for the reason explained above.
Also, am I correct in assuming that abstract declarations such as this only exist for type casting?
No, they can be used in function argument lists in a function declaration too. So,
int factorial(int);
is perfectly fine, so is
void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
EDIT
int (*) (*)
results in an error when i tried in visual studio and its not the way of declaring.
If you want a function pointer to return an integer data with pointer as argument the correct way of doing it is below.
int(*foo)(datatype *).
where data type can be
int ,float,char etc
and void and * are not the same .

What does (*) mean in plain C?

I can't get the meaning of the "(*)" expression in the following statement:
#define PySpam_System \
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
where
#define PySpam_System_NUM 0
#define PySpam_System_RETURN int
#define PySpam_System_PROTO (const char *command)
(excerpt from http://docs.python.org/2/extending/extending.html). What could that mean? (Excuse me for a dumb question). Resembles a function pointer, but with a very confusing syntax.
UPDATE: Thanks to Shahbaz and Jonathan things are getting mostly clear, but I still can't get two nuances:
Why const char *command, not just const char *. I thought that the name of the argument should be omitted in function pointer type declaration and type conversion? So it must not be omitted, but rather just can be?
Why (*(int (*)(const char *command)), not just (int (*)(const char *command)? What's the purpose of the outer (*[everything else here])? It's the optional dereferencing of function pointer to the function itself, right?
PySpam_System_RETURN (*)PySpam_System_PROTO
expands to:
int (*)(const char *command)
This is a function pointer type. So basically the following:
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
which translates to:
(*(int (*)(const char *command)) PySpam_API[0])
is calling the value of PySpam_API[0] as if it's a function with a const char* argument and an int return value (cast to function pointer). Note that this is still missing the arguments, so whoever uses the macro should give it arguments, such as:
PySpam_System("some string");
On your update:
The argument name is optional. They could have just written const char *. I believe the name was written for clarity. Right now, without looking anywhere else, I understood that the function takes a command, so it was helpful I'd say.
Again, you are right. The initial * dereferences the function pointer. In C, that's quite optional. It would be more symmetrical to put it, since you are dereferencing a pointer, but since not dereferencing a function pointer doesn't make sense, if you don't dereference it wouldn't make any difference, C would do the only sane thing for you. In fact, even if you put ****** instead of just one, it would still work.
Expand PySpam_System with the preprocessor, and you'd see:
(*(int (*)(const char *command)) PySpam_API[0])
The expression is (more or less) a cast to a 'pointer to function returning int and taking one argument of type const char *'. It would have to be followed by ("something") to convert the whole into a function call via the pointer to function. Thus, in the code, you might see:
PySpam_System("abc");
and the compiler would see:
(*(int (*)(const char *command)) PySpam_API[0])("abc");
and that is a call to the function stored in the array PySpam_API at index location 0. Obviously, the argument would probably not be a simple string literal, but a simple string literal is a representative const char *.
Question updates
Why const char *command, not just const char *. I thought that the name of the argument should be omitted in function pointer type declaration and type conversion? So it must not be omitted, but rather just can be?
Names for the arguments (such as command in the example) are optional in prototype declarations. There is also no rule stating that the name in the prototype declaration must match the name in the function definition. Sadly, C has not yet adopted the C++ convention that names are optional in the function definition if you are writing a function to conform to an interface but the particular implementation of the function does not need the argument. That is, in C++, you could write:
typedef int (*interface)(const char *cmd, int arg1, int arg2);
static int implementation(const char *cmd, int arg1, int) // C++, not C
{
return some_other_function(cmd, arg1, 23, 19);
}
The function implementation conforms to the interface type, but doesn't use the arg2 argument, but the compiler won't complain about the unused argument. C does not allow that convenience, so you get told about 'unused argument' even though you know perfectly well that it is unused. I believe there are compiler-specific ways around this particular problem.
Why (*(int (*)(const char *command)), not just (int (*)(const char *command)? What's the purpose of the outer (*[everything else here])? It's the optional dereferencing of function pointer to the function itself, right?
Right.
Note that there are two ways to invoke a function via a pointer to function, roughly the 'old' and the 'new' (where new means 'introduced and blessed by the C89 standard', so it is not exactly 'new').
The old notation required (give or take the prototypes which weren't available at the time):
#include <math.h>
double (*func)(double) = sin;
double x = (*func)(1.0);
with the parentheses and * around the function pointer. The idea is that if you have a pointer to a function, you need to dereference it to invoke the function. The more modern notation notes that the name of a function becomes a pointer to function (for example in the assignment), so you don't really need the (*func) notation. Hence the newer style is:
#include <math.h>
double (*func)(double) = sin;
double x = func(1.0);
Since I learned C when the old style was obligatory, I still prefer the slightly more verbose but completely unambiguous notation. The code in the PySpam_System macro uses the older notation too.
You can also play various silly games with function pointers, adding extra * and using a &, all of which are unnecessary.
double (*funca)(double) = &sin;
double (*func0)(double) = sin;
double (*func1)(double) = *sin;
double (*func2)(double) = **sin;
double (*func3)(double) = ***sin;
Only the func0 declaration is sensible; the rest are obfuscatory C.

"Incompatible pointer type" compiler warning for 4th argument of qsort

I'm trying to use the standard library's qsort to sort an array of wide characters:
wchar_t a = L'a';
wchar_t a1 = L'ä';
wchar_t b = L'z';
wchar_t chararray[] = {b, a, a1};
length = wcslen(chararray);
qsort(chararray, length, sizeof(wchar_t), wcscoll);
Now I think the functions involved have these prototypes:
int wcscoll(const wchar_t *ws1, const wchar_t *ws2);
void qsort(void *base, size_t num, size_t size, int (*comp_func)(const void *, const void *))
The results are completely as expected, but why am I getting the compiler warning "passing argument 4 of ‘qsort’ from incompatible pointer type"? And how can I cast wcscoll to fit the prototype?
The warning goes away if I define and pass in a separate comparison function:
int widecharcomp(const void *arg1, const void *arg2)
{
return wcscoll(arg1, arg2);
}
... but this one looks like it should have error handling for when the arguments are not of type wchar_t *.
You've done pretty much the right way. The gcc documentation for strcoll and wcscoll gives an example similar to this as the correct way to use strcoll or wcscoll with qsort.
/* This is the comparison function used with qsort. */
int
compare_elements (char **p1, char **p2)
{
return strcoll (*p1, *p2);
}
/* This is the entry point---the function to sort
strings using the locale's collating sequence. */
void
sort_strings (char **array, int nstrings)
{
/* Sort temp_array by comparing the strings. */
qsort (array, nstrings,
sizeof (char *), compare_elements);
}
This example actually does raise the warning that you want to get rid of, but again it can be gotten around by changing the char** to const void* in the arguments to compare_elements, and then explicitly casting to const char**.
You're right in observing that this is type-unsafe, but type safety is not exactly one of C's strong points. C doesn't have anything like generics or templates, so the only way that qsort can work on an arbitrary type is for its comparison function to accept void*s. It's up to the programmer to make sure that the comparison function is not used in a context where it may be passed arguments that are not the expected type.
That said, there is an error in your code. What the comparison function receives is not the elements to be compared, but rather pointers to the elements to be compared. So if the elements are strings, that means pointer-to-pointer. So when you write
return wcscoll(arg1, arg2);
You are actually passing wscoll a wchar_t** when it expects a wchar_t*. The correct way to do this, while suppressing the warning, would be:
int widecharcomp(const void *arg1, const void *arg2)
{
return wcscoll(*(const w_char_t**)arg1, *(const w_char_t**)arg2);
}
as ugly as that is.
Edit:
Just took another look at the top bit of your code. Your error is really twofold here. You're trying to use wcscoll to sort characters. It's a function meant to sort strings (which in C are pointers to nul-terminated sequences of characters). The above was written assuming you were trying to sort strings. If you want to sort characters, then wcscoll is not the appropriate function to use, but everything above regarding qsort still applies.
There are two problems: you've mixed up wchar_t and wchar_t*, and you've tried to pass off a wchar_t* as a void*.
First, you've told qsort to sort an array of wchar_t. But wcscoll doesn't compare wchar_t, it compares wide character strings which have the type wchar_t*. The fact that your comparison appears to have worked is due to your test data which just happens to work well under both interpretations.
If you wanted to sort characters, you need to call an appropriate function (I don't know the wide character API well enough to tell you which one). If you wanted to sort strings, you need to allocate an array of strings (of type wchar_t *).
Furthermore, even if you had an array of wchar_t*, you could not portably pass wcscoll as an argument to qsort. The issue is that there is no guarantee that wchar_t* and void* have the same representation. Some machines have word pointers that have a different representation from byte pointers; on such a machine, qsort would pass byte pointers to elements of the array to wcscoll, and this wouldn't work because wcscoll expects byte pointers. The solution is to write a trivial wrapper function that performs the conversion if necessary. A trivial wrapper is often necessary with qsort.
You've coded up your solution already (however, see other answers and edits at the end of this one about with the choice of the comparison function you're using and the data being passed to qsort()).
You could drop the wrapper function by casting the function pointer you pass to qsort() to the appropriate type, but I think using a wrapper is a better solution from a maintainability perspective. If you really want to avoid a wrapper function (maybe you're running into a measurable running into perf issue), you can cast like so:
qsort(chararray, length, sizeof(wchar_t), (int(*)(const void*,const void*))wcscoll);
Or make it arguably more readable using a typedef for the compare function type:
typedef
int (*comp_func_t)(const void *, const void *);
/* ... */
qsort(chararray, length, sizeof(wchar_t), (comp_func_t) wcscoll);
Unfortunately, the straight C qsort() can't be typesafe, so it can't have have "error handling for when the arguments are not of type wchar_t". You, the programmer, are responsible for ensuring that you're passing the correct data, sizes and comparison function to qsort().
Edit:
To address some of the problems mentioned in other answers about the types being passed ot the compare function, here's a routine that can be used to sort wchar_t using the current locale's collating sequence. The library might have something better, but I'm not aware of it at the moment:
int wchar_t_coll( const void* p1, const void* p2)
{
wchar_t s1[2] = {0};
wchar_t s2[2] = {0};
s1[0] = * (wchar_t*)p1;
s2[0] = * (wchar_t*)p2;
return wcscoll( s1, s2);
}
Also note, that the chararray you're passing to wcslen() isn't properly terminated - you'll need a 0 at the end of the initializer:
wchar_t chararray[] = {b, a, a1, 0};
You can't cast a function pointer to a different type, your current solution is as good it gets

Resources