alexisrdt
alexisrdt

Reputation: 326

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");
}

Upvotes: 2

Views: 167

Answers (2)

tstanisl
tstanisl

Reputation: 14107

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.

Upvotes: 1

Eric Postpischil
Eric Postpischil

Reputation: 222372

typedef void (*func_type)(int a, int b); declares func_type to be a type that is a pointer to a function. Then func_type func; declares func to be a pointer. Your proposed alternative, void func(int a, int b); declares func to be a function.

Since you can assign to a pointer, func = …; works with the first declaration. Since you cannot assign to a function, func = …; does not work with the second declaration.

To declare func to be a pointer to a function without using a typedef, use void (*func)(int, int);.

Upvotes: 1

Related Questions