I am reviewing some C code, but having a hard time understanding what Callback is exactly. Does anyone know what this means? I'm guessing that it is defining "Callback and x to be both a void *?
typedef void (*Callback)(bool x);
It makes a new type name Callback. Every Callback will be a pointer to a function taking a bool and returning void. In effect Callback will be an alias for that real type. So when you say:
Callback ptr = some_fun;
You're making a function pointer that points at some_fun. Function pointers are typically passed to other functions as arguments.
It declares a function pointer type by the name Callback which points to a function which takes a bool input parameter and returns a void.
Once you specify the statement, You can use Callback as a type to hold address of a function with the specifed type.
Refer the Clockwise spiral rule when in doubt.
Related
I am currently reading on the ways of passing arguments to C functions. And while reading I came to know that in C there are two methods to pass arguments as pass by value and pass by reference.
Then again I read that we can pass a pointer to the variable as a parameter too.
The beginnersbook website this method is mentioned as pass by reference.
In this example, we are passing a pointer to a function. When we pass a pointer as an argument instead of a variable then the address of the variable is passed instead of the value. So any change made by the function using the pointer is permanently made at the address of passed variable. This technique is known as call by reference in C.
I know that we can pass a pointer variable or the address of the variable with & operator when we need to change or access the original variable. I want to know whether this pass by pointer can also be called pass by reference.
Is pass by pointer also a method of pass by reference?
Technically, all arguments to functions in C are pass by value. The language doesn't have support for true references unlike C++.
Passing by reference can be emulated in C by passing (by value) the address of the variable you want to modify, then subsequently dereferencing that address to modify the pointed-to value. This is not true pass by reference, however.
Pointers in C are references. C 2018 6.2.5 20 says:
… A pointer type describes an object whose value provides a reference to an entity of the referenced type…
When you pass a pointer to a function, you are passing the function a reference to whatever object the pointer points to. The pointer itself is passed by value, but, because the pointer is a reference and you are passing it, the description that you are passing an object by reference is accurate.
Prior to the development of C++, there was no dispute about this; people said they were passing an object by reference to describe passing a pointer to the object. C++ adopted the word “reference” as a name for a new feature in its language, so, in C++ terminology, “reference” generally refers to that feature unless otherwise stated or made apparent by context. However, in C, we are not obliged by C++ terminology, and the original meaning of pass by reference remains accurate.
In general, all arguments to functions in 'c' are passed 'by values'. It means that If an argument is modified in a function, this modification will not be visible by the caller:
void foo(int val) {
...
val = newval;
...
}
void bar() {
foo(4);
}
The value val in the above example can be modified and used in 'foo' but 'bar' will not see the update.
In order to make an update visible in the caller, pointers are used.
void foo(int *arg) {
...
*arg = 5;
...
}
void bar () {
int x = 4;
foo(&x);
// x will be 5 here
}
In the above case the address of 'x' will be passed to the function foo and it will be used inside the function *arg to modify the value of 'x'.
One can modify the value of the pointer inside the foo, since it itself is passed by value
void foo(int *arg) {
arg = newAddress;
}
but function 'bar' will not see this modification as well.
So, there are no real 'references' in 'c', however some people use it in reference to the passing of pointers.
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…
I am a beginner in C.
For now I have a function like this
void mark_function(void *obj, void (*mark_obj)(void *));
To my understand, this a void function, and it has two parameter, first one is a void pointer,
and the second one is a another void function with a void parameter.
I tried a lot ways to call it, but it seems not work properly,either give me back the segmentation false or the pointer type not the same warning.
So What exactly means for this function? what parameters should pass in? and how to call it?
Any help?
Thanks alot!
Let's make it more clear first. You have a void function, called mark_function, which takes 2 parameters. The first parameter is a void pointer and the second parameter is a pointer to a function that returns void and takes as a parameter a void pointer. Let's create a function that will be apropiate to pass as parameter to mark_function.
void param(void *p) {
// function body
}
Assume a and b are 2 void pointers. I will not enter into details about their scope, but you need to pay attention to it: they must be available in the scope they are used.
Then, the mark_function will be called as:
mark_function(a, param);
Inside mark_function body you can have something like:
param(b);
, which is a call to the function passed as a parameter.
Long story short: the function pointers used as parameters are meant to make it possible for the function that requires them to perform different activities by calling different functions. The value of a pointer function is simply the name of a function that has the appropiate signature (return value and parameter list). Your function can use this to call the function provided as parameter as needed.
You should call the function with one pointer to an object, and one pointer to a function of suitable type.
int my_int;
void mark_function(void *obj, void (*mark_obj)(void *));
void my_func (void *vp)
{
/* Convert vp to a pointer to a real type */
int *ip = vp;
/* Do something with ip or *ip */
}
mark_function (&my_int, my_func);
A pointer to object (&my_int) can safely be convert to a void * and back to the same type. The resulting pointer is guaranteed to be identical to the original pointer. This allows mark_function() to perform some task regardless of the actual type that the pointer points to.
Typical examples of such tasks include sorting of arrays with a custom compare function provided by the caller, or maintaining linked lists without knowing the types of the object stored inside, an so on.
Pointers can be declared as pointing to mutable (non-const) data or pointer to constant data.
Pointers can be defined to point to a function.
My coworkers and I were discussing the use of "const" with pointers and the question came up regarding the use of const with function pointers.
Here are some questions:
What is the meaning of a pointer to a constant function versus a
pointer to a non-constant function?
Can a function be const?
Can a function be non-const (mutable)?
What is the proper (safe) syntax for passing a function pointer?
Edit 1: Function pointer syntax
typedef void (*Function_Pointer)(void); // Pointer to void function returning void.
void function_a(Function_Pointer p_func); // Example 1.
void function_b(const Function_Pointer p_func); // Example 2.
void function_c(Function_Pointer const p_func); // Example 3.
void function_d(const Function_Pointer const p_func); // Example 4.
The above declarations are examples of treating a function pointer like a pointer to an intrinsic type.
A data, variable or memory pointer allows for the above combinations.
So the questions are: can a function pointer have the same combinations and what is meant by a pointer to a const function (such as Example 2)?
In C, there's no such thing as a function being const or otherwise, so a pointer to a const function is meaningless (shouldn't compile, though I haven't checked with any particular compiler).
Note that although it's different, you can have a const pointer to a function, a pointer to function returning const, etc. Essentially everything but the function itself can be const. Consider a few examples:
// normal pointer to function
int (*func)(int);
// pointer to const function -- not allowed
int (const *func)(int);
// const pointer to function. Allowed, must be initialized.
int (*const func)(int) = some_func;
// Bonus: pointer to function returning pointer to const
void const *(*func)(int);
// triple bonus: const pointer to function returning pointer to const.
void const *(*const func)(int) = func.
As far as passing a pointer to a function as a parameter goes, it's pretty simple. You normally want to just pass a pointer to the correct type. However, a pointer to any type of function can be converted to a pointer to some other type of function, then back to its original type, and retain the original value.
According to the C spec (C99, section 6.7.3):
The properties associated with qualified types are meaningful only for
expressions that are lvalues.
When the spec says "qualified types", it means things defined with the const, restrict, orvolatile keyword. Snice functions are not lvalues, the const keyword on a function isn't meaningful. You may be looking at some sort of compiler-specific extension. Some compilers will throw an error if you try to declare a function as const.
Are you sure that you're looking at a pointer to a constant function and not a constant pointer to a function (that is, it's the pointer that's const, not the function)?
Regarding #4: see this guide for a helpful overview of creating, passing, and using function pointers.
Under C, there is no such thing as a const function. const is a type-qualifier, and so can only be used to qualify a type, not a function. Maybe you mean a const pointer to a function or a non-const pointer to a function?
In C++, methods can be const. If a method is const, it means that after you call that method, the object containing the method will be in the same state as before you called the method (none of the instance variables[1] have been modified). Thus, you can point to a const method and a non-const method, and those methods are different.
You can accept a function pointer in an argument list as retType (*variableName)(arguments).
[1] Unless they are mutable.
In C, functions can be const if you are in the world of GCC! Functions can be declared const through the use of attributes attached to declarations of functions and other symbols. It is basically used to provide information to the compiler on what the function does, even though its body is not available so that the compiler can do some kind of optimizations with it.
A constant function is generally defined in terms of a pure function.
A pure function is a function with basically no side effect. This
means that pure functions return a value that is calculated based on
given parameters and global memory, but cannot affect the value of any
other global variable. Pure functions cannot reasonably lack a return
type (i.e. have a void return type).
And now we can define what is a const function,
A pure function that does not access global memory, but only its
parameters, is called a constant function. This is because the
function, being unrelated to the state of global memory, will always
return the same value when given the same parameters. The return value
is thus derived directly and exclusively from the values of the
parameters given.
Here const doesn't imply anything about function mutability. But it is a function which doesn't touch global memory. You can assign normal pointers to such functions. Anyways the code region will generally ( forgetting self modifying code for a while ) be RO and you cannot modify it through the normal pointer.
Read the full insightful article here.
So when it comes to GCC Constant functions we are talking about optimizations and not function mutability.
1.What is the meaning of a pointer to a constant function versus a pointer to a non-constant function?
There is no difference between const and non-const: the function itself is not modifiable
Note: In C++ if the function is a member function of a class, const means that the state of the object within this function cannot be changed (member variables assigned to, non-const memeber functions called). In this case the const keyword is part of the member function's signature and therefore makes a difference in terms of the pointer.
2.Can a function be const?
See above.
3.Can a function be non-const (mutable)?
See above
4.What is the proper (safe) syntax for passing a function pointer?
All pointers to free functions can be cast to any other pointer to free function (i.e. their size is the same). So you could define a type for a (hypothetical) function: void f(); and convert all function pointers to this type to store. Note that you should not call the function via this common type: you need to cast it bact to its original pointer-to-function type, otherwise you get undefined behavior (and most likely crash)
For C++: pointers to member functions are not guaranteed to be convertible to pointers to free functions
1.
There is syntactically nowhere to place 'const' to make a function's contents constant.
You will run into 'function is not an l-value' error regardless if you have const or not.
typedef void (* FUNC)(void);
FUNC pFunc;
pFunc = 0; // OK
*pFunc = 0; // error: Cannot assign to a function (a function is not an l-value)
typedef void (* const FUNC)(void);
FUNC pFunc;
pFunc = 0; // error (const)
*pFunc = 0; // error: Cannot assign to a function (a function is not an l-value)
typedef void (const * FUNC)(void); // error: <cv-qualifier> (lol?)
2 & 3.
Function pointers- yes.. Function contents, doesn't look like.
4.
I don't think there is any way to make passing a function pointer safer. With all the consts in the world, the only thing you can protect is that 'SetCallback' can't change it's own local copy of the parameter.
typedef void (* const FUNC)(void);
void SetCallback(const FUNC const pCallback)
{
FUNC pTemp = pCallback; // OK (even though pTemp is not const!!)
pCallback = 0; // error (const)
}
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.