In the following program, &foo, *foo and foo points to the same memory adress :
#include <stdio.h>
int foo(int arg)
{
printf("arg = %d\n", arg);
return arg;
}
int main()
{
foo(0); // ok
(*foo)(0); // ok
(&foo)(0); // ok
printf("&foo = %lx\n", (size_t)(&foo));
printf("foo = %lx\n", (size_t)(foo));
printf("*foo = %lx\n", (size_t)(*foo));
return 0;
}
the output is :
arg = 0
arg = 0
arg = 0
&foo = 55eeef54c720
foo = 55eeef54c720
*foo = 55eeef54c720
Does anyone can explain this ? Thank you.
In the terminology of the C standard, any expression that has function type is a function designator. So, when used as an expression, the name of a function is a function designator.
There is nothing you can do with a function designator except take its address. You cannot add a number to a function designator, you cannot compare it to another function designator, and so on. Of course, you can call a function, but this is actually done by address, not by designator, as I will explain in a moment. Since there is nothing you can do with a function except take its address, C does this for you automatically. Per C 2018 6.3.2.1 4:
Except when it is the operand of the
sizeofoperator, or the unary&operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".
The result of this is:
&foo, the & takes the address of foo, so &foo is the address of foo.foo, the function designator is automatically converted to the address of the function, so foo is &foo.*foo, the function designator is automatically converted to the address of the function. Then the * operator converts this back to the function, which produces a function designator. Then the automatic conversion happens again, and the function designator is converted back to the address of the function, so the result of *foo is &foo.When you call a function, using the function ( argument-list... ) notation, the function must actually be a pointer to a function. Thus, you can call foo using (&foo)(arguments...). The automatic conversion simplifies the syntax so you can write foo(arguments...), but the call expression actually requires the address of the function, not the function designator.
Incidentally:
printf specifier for size_t values is %zx, not %lx.<stdint.h>, it defines a type intended for converting pointers to integers, uintptr_t. This is preferably to converting pointers to size_t.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