I am trying to create some macros that I can use to create my own unit testing library. My header file looks like this:
#ifndef _TEST_H_
#define _TEST_H_
#i
The suggested code never compiles as you are not supposed to dereference a void * pointer (how could you? There is no type information about the particular pointer.)
The way cmotley suggests in his comment is the correct way to do this although I would recommend a little improvement for the sake of readability:
typedef int (*tTestFuncSignature)(void)
#define test_run() tTestFuncSignature testfunc = hehe_stack_pop(tests); testfunc();
or even to avoid hidden name clashes using this macro:
#define test_run() ((tTestFuncSignature)hehe_stack_pop(tests))();
Either way you have to make sure (e.g. by contract) you only got valid pointers in your stack or have to test the pointer first before invoking the function.
Edit: Corrected code formatting
You can do it, but you're not supposed to do it by accident, so the syntax is made especially awkward. One does not cast the function pointer, but a pointer to a function pointer, then assigns that.
#define test_run() *((void**)&testfunc) = hehe_stack_pop(tests); testfunc(); return 0;
This turns &testfunc
into a pointer to a void*
, then dereferences it and assigns the value of another void*
to it, which is legal.
The C99 standard does not allow to convert between pointers to data (in the standard, “objects or incomplete types” e.g. char*
or void*
) and pointers to functions.
6.3.2.3: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 pointed-to type, the behavior is undefined.
One reason is that pointers to objects and pointers to functions do not have to be the same size. On an example architecture, the former can be 64-bit and the latter 32-bit.
You can cast from a pointer to a certain function type to a pointer to another function type, and this is the technique I recommend you use if you need to store function pointers in a data structure. Any function type will do. This means you cannot reuse a data structure intended for data pointers. You need to duplicate the data structure and change it to hold function pointers.
Do not forget to cast back to the proper function pointer type before calling, otherwise this is undefined behavior.
NOTE that, as pointed out by Andrew Mellinger, some compilers allow the conversion in each direction. C11's annex “J.5 Common extensions” lists:
J.5.7 Function pointer casts1 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).
Some POSIX interfaces, such as dlsym()
, also in effect mandate these conversions to be valid in the POSIX system's C compiler.