Can someone explain this line by line (character by character maybe, haha)?
typedef int (*funcptr)(); /* generic function pointer */
typedef funcptr (*ptrfuncptr)(); /* ptr to fcn returning g.f.p. */
funcptr start(), stop();
funcptr state1(), state2(), state3();
void statemachine()
{
ptrfuncptr state = start;
while(state != stop)
state = (ptrfuncptr)(*state)();
}
funcptr start()
{
return (funcptr)state1;
}
For example, I would like to know why there are () at the end of line 1. An answer like "that's just how you declare a pointer to a function" would be satisfying, but then when you declare a variable of that type, why only use "funcptr" without the ()?
Lines 4 and 5. Why do you have the () here? Those aren't functions, they're pointers to functions, right?
Line 9. Why doesn't "state" have ()? Still a pointer to a function as are the ones on lines 5 and 6.
Line 9. What is "start" without the ()?
Line 12. WHAT?! (I know what typecasting is. At least I think I do...)
Line 17. Why does "state1" require a typecast? It is of the type it's being cast as already. Or is it because it's missing the ()?
It would really help me to understand these concepts.
PS. This is for a microcontroller I'll use in an electronic Dummy Load I'm designing. Figured it's a good opportunity to learn more about C. The code is from http://c-faq.com/decl/recurfuncp.html
As noted in the question, this comes from the C FAQs web site. The question is:
Q: How can I declare a function that can return a pointer to a function of the same type? I'm building a state machine with one function for each state, each of which returns a pointer to the function for the next state. But I can't find a way to declare the functions—I seem to need a function returning a pointer to a function returning a pointer to a function returning a pointer to a function…, ad infinitum.
A: You can't quite do it directly. One way is to have the function return a generic function pointer (see question 4.13), with some judicious casts to adjust the types as the pointers are passed around:
And then there's a first example using the code shown in the SO question.
As the FAQ answer says, you can't create a function that returns a pointer to its own type of function, so you have to bludgeon the compiler into working.
Line 1: typedef int (*funcptr)();
This has the () at the end because without them, you'd have typedef int (*intptr); or typedef int *intptr; which is not what you want. The empty parentheses are an indeterminate — not empty — list of arguments. It is the way you declare a function pointer — before even trying to compile with my default compilation options, I modified the code to: typedef int (*funcptr)(void);.
A funcptr, therefore, is a pointer to a function that returns an int and (at least for the purposes of this discussion) takes no arguments.
Line 2: typedef funcptr (*ptrfuncptr)();
Don't try this without the intermediate type! This too is a pointer to a function, and the function returns a funcptr — and I used typedef funcptr (*ptrfuncptr)(void); to assert 'and takes no arguments'.
Line 4 & 5: funcptr start(), stop(); etc
These lines declare a set of 5 functions. Again, the argument lists are unspecified — so I'm going to treat them as having (void). These functions return a funcptr. However, their own type is not funcptr. This is the point made in the answer.
Indeed, treated as a name (without the parentheses), the type of start, stop, and state1 through state3 is ptrfuncptr — pointer to a function returning a funcptr.
Line 9: ptrfuncptr state = start;
The variable state is of type ptrfuncptr, and is initialized (without need for casting) to point at the function start. Note that this does not call the function; it merely initializes a variable, just as if you have int i = -37;, it initializes a variable i of type int to the value -37.
Line 12: state = (ptrfuncptr)(*state)();
Time to get the bludgeons out. This line contains a function call and a cast.
The original logic behind function pointers was the 'type mimics use' concept. For example, if you have:
int *p;
then in an expression, *p has the type int. With function pointers, you have:
int (*intfuncptr)();
and in an expression, (*intfuncptr)() represents an int; it is the result of invoking the function pointed at by intptrfunc. In pre-standard C, the (*pointer_to_function)() notation was the only way to use a pointer to function. Standard C allows you to omit the (* and ) around the pointer.
Thus, in modern notation, the line state = (ptrfuncptr)(*state)(); could also be written state = (ptrfuncptr)state();. When I learned C, this wasn't an option, so I still prefer the explicit 'this is invoking a function via a pointer to function' notation. The FAQ does mention this.
So, the line calls the function pointed to by state, and captures the return value in state. But the value returned by the function is a funcptr, not a ptrfuncptr, so we need to bludgeon the compiler into accepting that we know enough of what we're doing to remain silent. So, the (ptrfuncptr) cast does that.
Line 17: return (funcptr)state1;
Since start returns a funcptr, but state1 is a pointer to a function that returns a funcptr, the cast here is, once more, necessary to bludgeon the compiler into accepting the type mismatch. Without parentheses after it, state1 is just the name of the function, not an invocation of the function, and therefore has the type ptrfuncptr — pointer to a function returning a funcptr, not just funcptr which is what start is supposed to return. So, the cast is necessary.
For more mind-blowing function pointers, see:
Understanding typedefs for function pointer in C — examples, hint and tips, please
How typedef works for function pointers
Is it a good idea to typedefpointers? — general answer, no, but there's a strong exception for pointers to functions.
What are the various styles of defining a function returning a function pointer?
…and somewhere there's a question that discusses trivia like state = (ptrfuncptr)(******state)(); (using notation from this Q&A), and the mulitple stars work too…
Related
I am trying to understand what this means, the code I am looking at has
in .h
typedef void (*MCB)();
static MCB m_process;
in .C
MCB Modes::m_process = NULL;
And sometimes when I do
m_process();
I get segmentations fault, it's probably because the memory was freed, how can I debug when it gets freed?
It defines a pointer-to-function type. The functions return void, and the argument list is unspecified because the question is (currently, but possibly erroneously) tagged C; if it were tagged C++, then the function would take no arguments at all. To make it a function that takes no arguments (in C), you'd use:
typedef void (*MCB)(void);
This is one of the areas where there is a significant difference between C, which does not - yet - require all functions to be prototyped before being defined or used, and C++, which does.
It introduces a function pointer type, pointing to a function returning nothing (void), not taking any parameters and naming the new type MCB.
The typedef defines MCB as the type of a pointer to a function that takes no arguments, and returns void.
Note that MCB Modes::m_process = NULL; is C++, not C. Also, in C, the typedef should really be typedef void (*MCB)(void);.
I'm not sure what you mean by "the memory was freed". You have a static pointer to a function; a function cannot be freed. At most, your pointer has been reset somewhere. Just debug with a memory watch on m_process.
Let's take an example
typedef void (*pt2fn)(int);
Here, we are defining a type pt2fn. Variables of this type point to functions, that take an integer as argument and does not return any value.
pt2fn kk;
Here, kk is a variable of type pt2fn, which can point to any function that takes in an integer as input and does not return any value.
Reference:https://cs.nyu.edu/courses/spring12/CSCI-GA.3033-014/Assignment1/function_pointers.html
It's a function pointer. You get a SEGMENTATION FAULT because you are trying to make a call to a function which address is invalid (NULL).
According to your specific sample, the function should return no value (void) and should receive no parameters ().
This should work:
void a()
{
printf("Hello!");
}
int main(int arcg, char** argv)
{
m_process = a;
m_process(); /* indirect call to "a" function, */
// Hello!
}
Function pointers are commonly used for some form of event handling in C. It's not its only use though...
What is the proper C syntax for a function returning pointer to another function (which again may return a pointer to some thrid function etc)? I know that we can define a function as a local variable inside another function (but we need to know the address or it is useless):
int*(*a)(int) = (void*)0;
This is local variable a which represents a function which has int as a parameter and returns pointer to int, while the address of the function is 0. How can I have a function which returns, instead of pointer to int, a pointer to a function requiring char as a parameter and returning a pointer to int? This is what I've tried:
int*(*)(char)(*a)(int) = (void*)0;
But, it is a syntax error. Is there a way to do it, or maybe, the only way is to return void* and then to cast it again to function?
Edit
I am not looking only for a solution which works. I know it can be done using typedef or just by returning a generic pointer and then casting to another function. But, I am writting a code highlighter for C and I want to cover all cases which are defined by ISO C, so I am wondering does ISO C allow double returning functions, if yes, what is the proper syntax, if no, can it be found somewhere in documentation?
You could use typedefs to simplify this (and make sure you can actually understand the code a week later):
typedef int*(*FuncA)(int);
typedef FuncA(*FuncB)();
FuncB a = (void*)0;
Obviously use more descriptive names than I have done here.
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.