cfunction-pointersaddress-operator

Why can function pointers be used with or without the address of operator?


In the book, "Beginning C from Novice to Professional", the author does not use the address of operator when assigning a function to a function pointer. I typed in the code on my compiler both with and without the address of operator and it compiled and performed as expected both times. Why is this and which way would be preferred in an enterprise/business setting?

int sum(int, int);

int main(void)
{
    ...
    int (*pfun)(int, int);
    pfun = ∑
    pfun = sum;
    ...
}

int sum(int x, int y)
{
    return x + y;
}

Solution

  • This is a peculiarity of functions in C. The C standard says the following (C11 3.4.1p4):

    1. A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator, 65) 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''.

    I.e. sum that is a function designator is in any expression context, except when preceded by & or the said 2 operators is converted to a pointer to function. Of course in the expression &sum, the result is a pointer to a function. And ISO C does not allow sizeof or _Alignof be applied to a function, so in any expression that compiles, a function designator is either implicitly, or in the case of address-of operator, explicitly converted to a pointer to a function.

    Even the function call operator () requires that its operand be a pointer to function, hence you can call pfun without dereferencing: pfun(1, 2); and in sum(1, 2) sum is first converted to a pointer to a function, and then the function call operator is applied to this pointer.

    There are coding conventions that say that a call through a function pointer should use the dereference operator *, i.e. (*pfun)(1, 2), and likewise that the assignment be written as pfun = ∑.

    As such, writing (*pfun)(1, 2) would not make it clearer that it is a pointer as the same syntax would equally work for a function designator, i.e. (*sum)(1, 2); in the latter, sum is first converted to a pointer to a function since it is an operand to *; then the dereference converts the pointer to function to a function designator again, and then since it is an operand to a function call operator, it is converted to a function pointer again.

    Lastly, beware that pfun being an object of function pointer type, &pfun would actually get the address of the pointer variable, which is almost never what you wanted.