I'm having trouble with the following syntax in C:
float (*func(unsigned id))(float value) {
...
}
I understand that:
func
func
accepts one argument of type unsigned
called id
func
returns a pointer to a function that looks like: float f(float value)
But I don't understand why the return value of f
(the returned function pointer) is separated from its argument list.
Also, is: func(unsigned id)
an expression that evaluates to some pointer? Is this the reason why (*func(unsigned id))
works?
Can someone clarify this syntax step by step?
Function Pointer Syntaxvoid (*foo)( int ); In this example, foo is a pointer to a function taking one argument, an integer, and that returns void. It's as if you're declaring a function called "*foo", which takes an int and returns void; now, if *foo is a function, then foo must be a pointer to a function.
We can pass pointers to the function as well as return pointer from a function. But it is not recommended to return the address of a local variable outside the function as it goes out of scope after function returns.
To pass the value by pointer, argument pointers are passed to the functions just like any other value. So accordingly you need to declare the function parameters as pointer types as in the following function swap(), which exchanges the values of the two integer variables pointed to by its arguments.
We can retrieve a pointer to the first character in the sequence using the data() built-in function and pass after the return statement. Finally, we can operate on the char array using the returned pointer as needed.
The expression func(id)
returns a pointer to a function that takes a float as argument and returns a float.
float(*f)(float v); // pointer to a function
float val;
f = func(3); // returns a pointer to a function
val = (*f)(3.14); // calls the function pointed to with argument 3.14
Of course, you could rewrite the last statement:
val = (*func(3))(3.14); // take the ptr returned by func(3) and call the function pointed to.
If you have a function like:
float fct1 (float v) { return 2.0f*v+3.1f; }
you could write:
f = fct1; // reassign the pointer to function f to the adress of fct1
Let's look at the syntax. The C11 standard (draft N1570) states in 6.5.2.2 point 1: that "The expression that denotes the called function) shall have type pointer to function" and in point 3 that: "A postfix expression followed by parentheses () containing a possibly empty, comma-separated list of expressions is a function call."
This covers of course the usual cases:
val = fct1 (3.14); // fct1 is the function designator which adresses the function
val = (*f) (3.14); // (*f) the dereferenced function pointer, so it addresses the function
But the following is also valid according to standard:
val = f(3.14); // This works as well, because f is a pointer to a function
val = func(3)(3.14) // works also because func(3) is a pointer to a function
However first expression is ambiguous for the human reader, who might think of f as a function designator, expecting it to be defined somewhere. And the second is unusual as well. Furthermore, earlier versions of C didn't recognize them. My K&R edition for 1978 required the form (*f)() to call a function pointer.
A last syntactic remark: If you would define f as float *f (float);
it wouldn't be understood as a pointer to a function, but as a forward declaration of a plain function called f and returning a pointer to float. Why ? Because the C precedence rules give ()
a higer precedence than *
meaning that the compiler would understand it as (float *)(f(float))
. This is why an explicit parenthesis is required to show that (*f)
is the function pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With