views:

361

answers:

4

Hi all! This is actually a non-critical question, but I get this warning most of the time I use function pointers and still couldn't figure out why on my own. Consider the following prototype:

typedef void * Pointer;
void tree_destroyLineage(Tree greatest_parent, void *dataDestructor(Pointer data));

And so far I can compile my thousand-line-long code and get zero warnings. So I'm assuming I wrote the declaration correctly. But then I call it in code, passing free as my destructor, since the data stored in the tree nodes are simple structs:

tree_destroyLineage(decision_tree, free);

And this makes me get a "warning: passing argument 2 of 'tree_destroyLineage' from incompatible pointer type" message. My first hypotesis was that the compiler couldn't figure out at compile time that "Pointer" and "void *" are the same thing, so I tried both creating another function with the exact same types of the function pointer that "repasses" the call to free() and changing the function pointer declaration to accept a void * instead of a Pointer. Both approaches gave me the very same warning at the very same place.

What am I doing wrong and how do I solve it?

Thanks in advance.

+2  A: 

Try this:

void tree_destroyLineage(Tree greatest_parent, void (*dataDestructor)(void *data));

Using a typedef for a void pointer is just plain silly.

Edit: the problem is that, without the parenthesis around *dataDestructor, the compiler thinks that the function returns void *, rather than void. The parenthesis tell the compiler that the function returns void, but is a pointer to a function.

Zifre
Thanks for the help. As I told in my reply comment in my original post, I got the idea of "typedeffing" void * from GLIB (GTK+ 'base' library) when I was building my custom "generic" containers library. So, you can blame them and call them silly. =)
Rafael Almeida
Yes, I consider GLib silly too :). The whole idea of GLib is flawed. They are basically trying to write C++ in C.
Zifre
Sure "simulating" functionalities of a more recent language in an older one is anti-logical, so I've been told, but GLIB does its job very well. And time is a serious matter when you have the constraint to use only pure C and you are spending your time implementing a thousand of list types while you should really be focusing on what your hybrid-greedy-bruteforce algorithms does with all the trees it creates.
Rafael Almeida
I think some of GLib is silly (e.g. gchar is always exactly equivalent to char), but other parts are very useful (like GHashTable).
Matthew Flaschen
+10  A: 

I believe the correct signature for a function like free is:

void (*freefunc)(void*)

not

void *dataDestructor(Pointer data)
Unknown
Thanks, this solves it even if I keep using Pointer instead of "void *". After JF's post I realized what was going wrong.
Rafael Almeida
+7  A: 

I'm not sure about your library, but my free has no return value (i.e., it's void). It doesn't return a void pointer.

If you want the 2nd argument to be a pointer to a function which returns void and takes as an argument a void pointer, I believe what you want is:

void (*fn)(void*)

and not

void *fn(void*)

which is what you have.

JF
Thanks, this made me see the difference. My destructor function was being declared as void * instead of void, and this was causing the problem.
Rafael Almeida
+3  A: 
void tree_destroyLineage(Tree greatest_parent, 
                          void *dataDestructor(Pointer data));

should be:

void tree_destroyLineage(Tree greatest_parent, 
                          void (*dataDestructor)(Pointer data));
anon