0

I worte a test program to understand callback functions and function pointers.The program is given below.

My question is while assigning

cb_display = (void*)display_struct; 

I have to cast the function to a void*. Why is this required even when the return type of function is void?

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int a; char b[16]; }myst_t; void (*cb_display)(void*); void display_struct(myst_t *st){ fprintf(stdout, "a -> %d b -> %s \n",st->a,st->b); } int main() { myst_t myst; myst.a = 789432; strncpy(myst.b,"helloabcd",9); cb_display = (void*)display_struct; cb_display(&myst); return 0; } 
2
  • 3
    The cast invokes undefined behaviour. void * can only be converted to/from an object pointer, not a function pointer. If you do it right, thre is no need for a cast either. Get your types right! Commented Sep 14, 2015 at 21:07
  • 3
    The return types match however the argument types differ (void* vs. myst_t*). Commented Sep 14, 2015 at 21:08

2 Answers 2

3
cb_display = (void*)display_struct; 

is actually also not valid in C. Don't do it. You cannot assign a void * to a function pointer.

To fix your issue declare your function pointer as:

void (*cb_display)(); 

It means it matches a function that return no value and takes an unspecified number of parameters. You then don't need any cast. Also please note as it was pointed by Olaf in the comments that a function declarator with () while valid is an obsolescent C feature.

Of course if you will only pass functions like display_struct with a myst_t * parameter, you can also declare cb_display as: void (*cb_display)(myst_t *);

Sign up to request clarification or add additional context in comments.

18 Comments

@liv2hak Yes, it's the best option. Actually the assignment with no conversion at all must work well, but I'm not sure if it's an undefined behavior or not.
omitting void for an empty argument list (non-prototype declarator) is actually an obsolencence legacy construct and should not be used. void (*cb_display)(void); is the correct form. It is in general aq very dangerous declaration. The correct form here would be as you edited to have the correct argument types.
@Olaf fair enough, I answered from memory I didn't read your link. Added an edit in my answer.
@EldarDordzhiev it's not valid with void * cast and it's also not valid without the cast, the two function types are different.
"... as pointer types in C are all identical" Where did you get this nonsense? An int * is certainly different from a char *, etc! And function pointers are even more different than object pointers. It's just that all object pointers can be converted to/from void * - the universal object pointer. Yet, functions are no objects in C. This is the reason you should aviod void * whereever possible and use properly typed pointers. With great flexibility (of the language) comes great responsibility (of the programmer).
|
0

Changing void (cb_display)(void);

To typedef void (cb_display)(void);

May work.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.