64

Normally, when declaring some variable, you put its type before it, like:

int a;

a function pointer may have type like: int(*)(int,int), in case we point to a function that takes two integers and returns an integer. But, when declaring such a pointer, its identifier is not after the type, like:

int(*)(int,int) mypointer;

instead, you must write the identifier in the middle:

int(*mypointer)(int,int);

why is this so?

Cristik
  • 30,989
  • 25
  • 91
  • 127
user1941583
  • 761
  • 1
  • 5
  • 9
  • 2
    Search for "Declaration reflects use". – Mr Lister Jan 01 '13 at 22:19
  • This Q helps explain Typedef syntax `typedef old-type alias-identifier` but example function pointer examples like "typedef int (*sum_func)(int,int);" don't match the syntax... Until now! – Kevin Sep 18 '18 at 00:11
  • Because the language is badly designed. That's it! – iono Jul 26 '22 at 16:12

4 Answers4

36

I explain this in my answer to Why was the C syntax for arrays, pointers, and functions designed this way?, and it basically comes down to:

the language authors preferred to make the syntax variable-centric rather than type-centric. That is, they wanted a programmer to look at the declaration and think "if I write the expression *func(arg), that'll result in an int; if I write *arg[N] I'll have a float" rather than "func must be a pointer to a function taking this and returning that".

The C entry on Wikipedia claims that:

Ritchie's idea was to declare identifiers in contexts resembling their use: "declaration reflects use".

...citing p122 of K&R2.

Community
  • 1
  • 1
detly
  • 29,332
  • 18
  • 93
  • 152
27

This structure reflects how a normal function is declared (and used).

Consider a normal function definition:

int foo (int bar, int baz, int quux);

Now consider defining a function pointer to a function of the same signature:

int (*foo) (int, int, int);

Notice how the two structures mirror each other? That makes *foo much easier to identify as a function pointer rather than as something else.

atomicinf
  • 3,596
  • 19
  • 17
19

If you're dealing with a function (not a pointer to one), the name is in the middle too. It goes like: return-type function-name "(" argument-list ")" .... For example, in int foo(int), int is the return type, foo the name and int the argument list.

A pointer to a function works pretty much the same way -- return type, then name, then argument list. In this case, we have to add a * to make it a pointer, and (since the * for a pointer is prefix) a pair of parentheses to bind the * to the name instead of the return type. For example, int *foo(int) would mean a function named foo that takes an int parameter and returns a pointer to an int. To get the * bound to foo instead, we need parentheses, giving int (*foo)(int).

This gets particularly ugly when you need an array of pointers to functions. In such a case, most people find it easiest to use a typedef for the pointer type, then create an array of that type:

typedef int (*fptr)(int);

fptr array[10];
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
11

I had seen at some places function pointers declared as

int (*foo) (int a, int b);

and at some places a and b are not mentioned and both still works.

so

int (*foo) (int, int)

is also correct.

A very simple way that I found to remember is as mentioned below:

Suppose function is declared as:

int function (int a , int b);

Step1: Simply put function in parentheses:

int (function) (int a , int b);

Step2: Place a * in front of function name and change the name:

int (*funcPntr) (int a , int b);

PS: I am not following proper coding guidelines for naming convention etc. in this answer.

Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37
  • Both `int (*foo) (int a, int b);` and `int (*foo) (int, int);` works because a parameter's name in a function prototype is optional in C. – uzluisf Apr 02 '21 at 14:24