Why does this function call work with and without the "address of" operator (&
)?
If someone could give a simpler example of the same issue, I would understand the main idea.
#include <iostream>
using namespace std;
void sum(int, int);
void fun(int, int, void (*)(int, int));
int main()
{
fun(3,4, &sum); // Why does this line work with and without the `&`?
return 0;
}
void sum(int a, int b)
{
cout << a b;
}
void fun(int a, int b, void (*ptr)(int, int))
{
(*ptr)(a,b);
}
CodePudding user response:
C 2018 6.3.2.1 3 says:
A function designator is an expression that has function type. Except when it is the operand of the
sizeof
operator, 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".
C performs the same automatic conversion, although the specification of this is spread across several clauses in the standard.
Thus, in fun(3,4, &sum);
, sum
is not converted to a pointer because it is the operand of &
. But then the &
takes the address, producing a pointer to the function. Alternatively, in fun(3,4, sum);
, sum
is automatically converted to a pointer to the function, producing the same result.
In (*ptr)(a,b)
, the *
and parentheses are unnecessary. The function call operator, (…)
, technically takes a pointer to a function as its left operand, so ptr(a, b)
supplies that pointer. In (*ptr)(a,b)
, *ptr
dereferences the pointer, producing a function designator. Then this function designator is automatically converted back to a pointer. Thus, the expression is equivalent to (&*ptr)(a, b)
, which is equivalent to ptr(a, b)
.
In fact, if you write (**ptr)(a, b)
, *ptr
becomes &*ptr
as above, and then *&*ptr
produces the function designator again, and that is automatically converted again, yielding &*&*ptr
, which is equivalent to ptr
. You can add any number of *
operators, and they will all be undone by the automatic conversions; you can write (**************ptr)(a, b)
.
There is also an automatic adjustment of function parameter declarations corresponding to the automatic conversion. If a parameter is declared to be a function, as in the ptr
of void fun(int a, int b, void ptr(int, int))
, it is automatically adjusted to be a pointer to a function, as if it had been written void fun(int a, int b, void (*ptr)(int, int))
.