Compiling with gcc8:
#include <stdio.h>
void some_func(void f1(void), void (*f2)(void))
{
printf("%d\n", f1);
printf("%d\n", f2);
}
Gives (only) the following warnings:
<source>:11:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'void (*)(void)' [-Wformat=]
printf("%d\n", f1);
<source>:12:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'void (*)(void)' [-Wformat=]
printf("%d\n", f2);
Why is the type of f1
the same as f2
? Only f2
is declared as a function pointer. I would expect f1
not to compile at all, as it names a function type, not a function pointer. What is the rule that says, that a function type inside a function parameter list changes to a pointer to that function type?
But we can pass the reference of a function as a parameter by using a function pointer. This process is known as call by reference as the function parameter is passed as a pointer that holds the address of arguments. If any change made by the function using pointers, then it will also reflect the changes at the address of the passed variable.
Function pointers are similar, except that instead of pointing to variables, they point to functions! Consider the following function: Identifier foo is the function’s name. But what type is the function? Functions have their own l-value function type -- in this case, a function type that returns an integer and takes no parameters.
For example, in below program, user is asked for a choice between 0 and 2 to do different tasks. 6) Like normal data pointers, a function pointer can be passed as an argument and can also be returned from a function. For example, consider the following C program where wrapper () receives a void fun () as parameter and calls the passed function.
One interesting note: Default parameters won’t work for functions called through function pointers. Default parameters are resolved at compile-time (that is, if you don’t supply an argument for a defaulted parameter, the compiler substitutes one in for you when the code is compiled). However, function pointers are resolved at run-time.
Because the standard (6.7.6.3p8) says that
A declaration of a parameter as ''function returning type'' shall be adjusted to ''pointer to function returning type'', as in 6.3.2.1.
It's similar to how arrays parameters are adjusted to pointers (6.7.63.p7) , if you think about it.
void some_func(void (void));
void some_func(void (*)(void));
are compatible declarations, just like:
void other_func(char string[]);
void other_func(char *string);
are.
Note that the adjustment doesn't make void some_func(void (*)(void)
compatible with void some_other_func(void (**)(void)
or void yet_another_func(void (*****)(void)
and that as far as functions are concerned, declarations don't really reflect use anymore, (despite that being the intention of the language's original author). In standardized C, due to how function identifiers decay to pointers and due to how it doesn't matter whether you use a function type or a function pointer type to make a call, you can call any function with arbitrarily many *
:
#include <stdio.h>
int main()
{
(*puts)("hello world");
(******puts)("hello world");
(***&*&*puts)("hello world"); //& cancels a * as per 6.5.3.2p3
int (*p)(char const*) = puts;
int (**pp)(char const*) = &p;
int (***ppp)(char const*) = &pp;
(**ppp)("hello world"); //at least two asterisks required here
}
Because in C, in that case, the function name itself is a function pointer. See this answer: Why is using the function name as a function pointer equivalent to applying the address-of operator to the function name?
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