Search code examples
cfunction-pointers

Defining a function through a pointer


I have the following code:

typedef void (*func_type)(int a, int b);
func_type func;

int main()
{
   func = (func_type)GetProcAddress(NULL, "func");
}

This code works fine, but I would like to change func_type func; to void func(int a, int b); (because code completion shows "func_type" instead of "func" when typing the parameters). But when I try to change this, the compiler tells me that in the main function "expression must be a modifiable lvalue". I tried to look online but did not find an answer to my problem. Code becomes this:

typedef void (*func_type)(int a, int b);
void func(int a, int b);

int main()
{
   func = (func_type)GetProcAddress(NULL, "func");
}

Solution

  • Functions in C behave similar to arrays. They both decay to pointers. Whenever function name is used it automatically decays to a pointer to this function. The exceptions are & and sizeof operators. Operator sizeof does not accept a function as operand. That is why foo and &foo are equivalent.

    Functions itself are non-modifiable by design. Any attempt of modifying it i.e. by memcpy-ing to a function pointer is undefined behaviour.

    Surprisingly, function call operator () does not take a function as operand but a pointer to a function.

    Therefore, a function call

    foo(1);
    

    is actually

    (&foo)(1);
    

    Because foo decays to &foo before evaluation of the function call.

    That is why one can interchangeably use functions and function pointer in function call operands.

    void foo(int) { ... }
    void (*bar)(int);
    
    foo(1); // foo decays to &foo which is a function pointer
    bar(2); // bar is already a function pointer
    

    To solve the original problem I suggest keeping func be a function pointer, that initially points to some dedicated function but it can be overwritten later on:

    typedef void func_type(int,int);
    
    void default_func(int a, int b) { ... }
    
    funt_type* func = default_func; // decays to &default_func !
    
    int main()
    {
       func(1,2); // calls default_func
       func = (func_type*)GetProcAddress(NULL, "func");
       func(3,4); // calls func from dll/so
    }
    

    I've decided to use function types (not function pointer types) what is a bit un-orthodox. IMO, it make syntax more visually pleasing, and it is easier to parse by a human. Moreover, it is explicit about what is a pointer what is not.