Search code examples
cfunction-pointersimplicit-conversionfunction-declaration

Why does function pointer in c does not have to be pointer at all?


Having this:

#include <stdio.h>
#include <stdlib.h>

int do_op(int (*op)(int,int),int a, int b){ return op(a,b); }
/*int do_op(int (op)(int,int),int a,int b){return op(a,b);} */
int add(int a, int b){ return a+b; }
int mul(int a, int b){ return a*b; }

int main(){
    printf("add:%i;mul:%i\n",do_op(add,5,10),do_op(mul,5,10));
}

From what I know about function pointer so far, is their "type" is of return value's type. (Does not know how it is implemented in gas, wheter the return value is in %rax before ret? just an detail), however what is the point of a reference to a function, when it does not have to be reference at all? What does it mean, when it is not pointer? (like (op)), is then the function used by value (not address)? But function in general does not have value, it has only start address in %rbi and after it finishes, it is retuned back to upper function by ret, so what does it mean in c, a function "pointer" is not pointer? (give some examples please)

The question is relating to the comment in the code, where the (op) part is not a pointer, but still work. So is it a pointer or not?


Solution

  • The type of a function pointer is not its return type. It is the type of the function pointed to.

    In the case of the parameter int (*op)(int,int), the type of op is "pointer to function which takes an int and an int, and returns int".

    You could also define the parameter as int op(int,int) in which case the type of op is "function which takes an int and an int, and returns int".

    Because function pointers point to code, they don't have a "value" in the sense that objects do. In fact, anyplace you specify an expression with a function type it is automatically converted to a pointer to a function. So you can declare the parameter op as int (*op)(int,int) or int op(int,int) and they will be exactly the same.

    Section 6.3.2.1p4 of the C standard says the following regarding function types:

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

    Section 6.7.6.3p8 also says the following regarding a function type as a parameter:

    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 is because of this that a parameter of function type is allowed. A variable of function type that is not a parameter is not useful because it can't be initialized or assigned.