Home > Software engineering >  Function (pointer) as an argument
Function (pointer) as an argument

Time:10-12

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)).

  • Related