To aid with some precise memory allocation that I'm doing in C, I'm trying to get the sizeof a function pointer for a function with return type void that takes no parameters.
However, when I do sizeof (void (*)()), I generate a compiler warning:
function declaration isn’t a prototype [-Wstrict-prototypes]
How do I get the size that I'm looking for?
That is an old style function definition, it is missing the argument list, so add them:
sizeof( void(*)(void) )
For readability purposes, I recommend declaring a type for the signature of any function you'll want have some pointer to:
typedef void my_sigt(void);
then, to declare a pointer to such a function, code:
my_sigt* funptr;
and to get its size code sizeof(my_sigt*) (or sizeof(funptr) if you have such a variable funptr)
BTW, I am not sure that the C99 standard guarantees that every function pointer has the same size (or has the same size as some data pointer). But POSIX requires that (in particular, to be able to use dlsym for dynamic linking of such functions).
Related
I have been reading about the restrict keyword and every example I've seen uses it when defining a function.
void foo (int *restrict bar, float *restrict baz);
I have been reading through articles on it and wondering if this would be something valid.
int main()
{
int *restrict bar = malloc(sizeof(int));
//... code using bar
return 0;
}
I tested it with gcc and I am not receiving any compiler warnings, but will it actually do anything? Will the compiler pick up that this pointer for it's life will not overlap and that it will not be shared by any other pointer or will it only work when used when defining a function?
The restricted 'bar' in main tell the compiler that the data will not be referenced via any other pointer. Depending on what main does, it might help with optimization of 'main'. If the only manipulation of bar is in function foo, there is no need to make it restrict.
As a side note, on Linux/gcc, the 'malloc' is tagged with __attribute__ ((__malloc__)), which tells the compiler that the returned value is restrict pointer, which will allow the compiler the perform the required optimization, if relevant. See: understanding malloc.h difference: __attribute_malloc__ https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
malloc
This tells the compiler that a function is malloc-like, i.e., that the pointer P
returned by the function cannot alias any other pointer valid when the function
returns, and moreover no pointers to valid objects occur in any storage addressed by P.
Using this attribute can improve optimization. Compiler predicts that
a function with the attribute returns non-null in most cases.
Functions like malloc and calloc have this property because they
return a pointer to uninitialized or zeroed-out storage. However,
functions like realloc do not have this property, as they can return a
pointer to storage containing pointers.
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_
#include <stdio.h>
#include "hehe_stack.h"
static hehe_stack* tests;
typedef int (*testfunc)();
#define test_init() tests = hehe_stack_init();
#define test_register(test) hehe_stack_push(tests, test);
#define test_info() fprintf(stdout, "running %s :: %s \n", __FILE__, __func__);
#define test_run() testfunc = (int (*)()) hehe_stack_pop(tests); testfunc(); return 0;
#endif
In each test .c file I want to push a number of function pointers into the tests stack and then pop each function pointer out of the stack and call it. My stack pop method returns a void pointer, and the function pointer that I am pushing onto it returns an int and takes no parameters. Is my syntax incorrect? I feel like I should be able to do this.
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 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).
Some POSIX interfaces, such as dlsym(), also in effect mandate these conversions to be valid in the POSIX system's C compiler.
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 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
I have microcontroler that I am working with. When debugging it is necessary to call a function from that is hard coded in ROM. Technical Reference shows how to do this:
# define Device_cal (void(*)(void))0x3D7C80
and calling procedure looks like this:
(*Device_cal)()
I can't understand what actually happens here, so my question is:
How does it work?
void (*) (void) is a type. It's a pointer to a function that takes no parameter and returns void.
(void(*)(void)) 0x3D7C80 casts the 0x3D7C80 integer to this function pointer.
(*Device_cal)() calls the function.
(Device_cal)() would do the exactly the same.
The parentheses around *Device_cal and Device_cal are required because otherwise the cast to the integer would not have the higher precedence.
The #define causes (*Device_cal)() to be expanded into this immediately before compiling:
(*(void(*)(void))0x3D7C80)()
The void(*)(void) is a declaration for a function pointer that takes void and returns void types. The (*()) represents a cast for the next token in the expression (0x3D7C80). Thus this asks to treat the data at location 0x3D7C80 as a function. The final () calls the function with no arguments.
well, you "define" a pointer to function, and call it.
void(*)(void) mean a pointer to function, that gets no arguments, and return void.
If you cast 0x3D7C80 to that type, and call it, you basically call the function that its address is 0x3D7C80.
This is not an answer (that has already been done satisfactorily), but some advice:
I would suggest the following method instead:
typedef void (*tVOID_ROMFUNCTION_VOID)( void ) ;
tVOID_ROMFUNCTION_VOID Device_cal = (tVOID_ROMFUNCTION_VOID)0x3D7C80 ;
Device_cal() ;
That way you can create any number of global function pointers on initialisation while the calls look like normal statically linked functions. And you avoid confusing pre-processor macros voodoo at the same time.
By creating different function-pointer types with different signatures, the compiler will be able to perform some parameter type checking for you too.
The symbol is pasted in which creates a temporary (un named ) pointer to a function at a fixed memory location and then calls it via dereferencing.
I have a function pointer inside a struct that gets dynamically set at runtime to the address of another function in various places in my code. It is defined in my header file like this:
void *(*run)();
During compile time, I get the following warning about this:
warning: function declaration isn't a prototype
This warning is benign, because the pointer is used in many places in my code to call the function it points to, and everything works just fine. However, I would really like to silence the warning.
If I change it to this:
void *(*run)(void);
I get compile errors whever I use it, because the various functions that make use of the pointer have different numbers of arguments, and saying void inside the parenthesies tells the compiler it accepts no arguments.
I can't use a va_list or anything fancy like that, as this is simply a pointer to another function, and I use a single pointer for them all because it keeps the code clean and simple.
I can silence the warning with adding this to my compiler flags:
-Wno-strict-prototypes
But I'd rather not have to disable compiler warnings with flags if I can avoid it.
So my question is: How do I notate this function pointer in the code in such a way that the compiler is satisfied with the fact that it accepts any number of any kind of arguments?
The code works perfectly. I just want the warning to go away.
Store the pointer as a void * and cast to the appropriate function pointer type when necessary? Keep in mind that it isn't necessarily safe to call one type of function pointer as if it were another type, so the warning you're starting out with isn't entirely invalid.
You can cast a function pointer like so:
void *genericPointer = ...;
void (*fp)(int, int) = genericPointer;
fp(123, 456);
Note that:
There's no explicit casting necessary here, as void * can always be cast to any pointer type.
The initial "void" before (*fp) is the return type of the function pointer.
You are trying to do things clean - i.e. involve the compiler in checks, but the design you invented simply cannot be clean by its principle. You cannot involve compiler in prototype checks this way, because you always must know, which parameters to pass at this particular case in runtime. Compiler cannot check this and if you make a mistake, segmentation fault is on the way.
But if I remember well, something like this was maybe used also in linux kernel (?). The solution is to have a general pointer (like the one you have) and each time you call a particular function you just typecast it to the pointer to function with the particular arguments. You may need to typecast it to void * first to silence the compiler again :-)
In C, when you call a function without a prototype visible, default argument promotions are applied to all of the arguments that you pass to the function. This means that the types that you actually pass do not necessarily match the types received by the function.
E.g.
void (*g)();
void f()
{
float x = 0.5;
g(x); // double passed
}
This means that you need to know that the function that you are actually calling has a compatible signature to that implied by the arguments that you are passing after promotion.
Given that you need to know this in any case you must know the function signature of the actual function being called at the call site which is using the function pointer. With this knowledge it is usually simpler and cleaner to use a function pointer with the correct prototype and you can avoid default argument promotion entirely.
Note that as you are defining your functions with prototypes, when you assigned a pointer to your function to a function pointer without a prototype you effective converted, say, a void(*)(int, int) to a void(*)() so it is completely correct and desirable to perform the reverse conversion before calling the function. gcc allows both these conversions without emitting any warnings.
E.g.
void PerformCall( void(*p)() )
{
if (some_condition)
{
// due to extra knowledge I now know p takes two int arguments
// so use a function pointer with the correct prototype.
void(*prototyped_p)(int, int) = p;
prototyped_p( 3, 4 );
}
}
Try typedefing the function pointer declaration and then have the caller explicityly cast it:
typedef void *(*run)();
//when calling...
void my_foo() {}
run r = (run)my_foo;
If the different function signatures are known, use a union. Otherwise, use a pointer of type void (*)(void) (actually, any function pointer type would do) to hold the generic pointer and convert to the proper type when setting the value and calling the code.
Example using a union:
union run_fn
{
void *(*as_unary)(int);
void *(*as_binary)(int, int);
};
struct foo
{
union run_fn run;
};
void *bar(int, int);
struct foo foo;
foo.run.as_binary = bar;
void *baz = foo.run.as_binary(42, -1);
Example using explicit casts:
struct foo
{
void (*run)(void);
};
void *bar(int, int);
struct foo foo;
foo.run = (void *(*)(int, int))bar;
void *baz = ((void *(*)(int, int))foo.run)(42, -1);
Don't use a void * to hold function pointers - such a conversion is unspecified by the ISO C standard and may be unavailable on certain architectures.
Ignoring the warning and using your code as-is is actually also a possibility, but keep in mind that any function argument will be subject to the default argument promotions and it's your responsibility that the promoted arguments properly match the declared parameters.
I've searched but couldn't find any results (my terminology may be off) so forgive me if this has been asked before.
I was wondering if there is an easy way to call a void* as a function in C without first declaring a function pointer and then assigning the function pointer the address;
ie. assuming the function to be called is type void(void)
void *ptr;
ptr = <some address>;
((void*())ptr)(); /* call ptr as function here */
with the above code, I get error C2066: cast to function type is illegal in VC2008
If this is possible, how would the syntax differ for functions with return types and multiple parameters?
Your cast should be:
((void (*)(void)) ptr)();
In general, this can be made simpler by creating a typedef for the function pointer type:
typedef void (*func_type)(void);
((func_type) ptr)();
I should, however, point out that casting an ordinary pointer (pointer to object) to or from a function pointer is not strictly legal in standard C (although it is a common extension).
I get awfully confused when casting to function types. It's easier and more readable to typedef the function pointer type:
void *ptr = ...;
typedef void (*void_f)(void);
((void_f)ptr)();
In C++: reinterpret_cast< void(*)() > (ptr) ()
The use of reinterpret_cast saves you a set of confusing parentheses, and the < > clearly sets the type apart from the call itself.