1

From this question How do function pointers in C work?, I tried it here:

#include <stdio.h>

int add(int a, int b){ return a+b; }

int add2(int(*fp)(int,int)){
    return fp(2,3);
}

int (*factory(int n))(int,int){
    printf("got params:%i\n",n);
    return add;
}

int main(){
    int *p(int,int) = factory(5); // it has to be (*p)
    printf("%i\n",p(1,2));
}

There was mentioned

the standard says that a function name is converted to the address of the function

So it should work without the parethesis anyway, when it is converted to address.

But it gives error:

function ‘p’ is initialized like a variable

But is should be function pointer, not just function. So how is it with the syntax?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45

5 Answers5

3

The problem is that

int *p(int,int)

declares p as a function (int, int) returning a pointer to an int.

You need

int (*p)(int,int)

which declares p as a pointer to a function (int, int) returning an int

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • This is why I like declaring the first variant as `int* p(int, int)`, which *removes all doubt* (despite most of my colleagues protestations to the contrary). – Robert Harvey Aug 04 '20 at 23:51
  • 1
    @RobertHarvey It's misleading to write `int*`. It's contrary to the syntactic precedence. It implies that `int` and `*` bind more tightly than `*` and the declarator, which is untrue. Experienced C programmers know that primaries bind more tightly than unary operators, so `int *p(int, int)` is perfectly clear, and is equivalent to `int *(p(int, int))`. Declarator syntax matches use syntax. Also `int *p, *q;` is *much* clearer than `int* p, *q;`, which is truly misleading and strongly suggests that `q` is `int **` rather than `int *`. – Tom Karzes Aug 05 '20 at 00:24
2

The compiler emits error on your code - so the code is invalid.

int *p(int, int); - declares the function returning pointer

int (*p)(int, int); - defines pointer to the function.

You can use typedefs to use "usual pointer syntax:

typedef int functype(int, int);

functype *p; // defines the function pointer `p`

BTW your example will be easier to read when we use typedefs

typedef int func(int, int);

int add(int a, int b){ return a+b; }

int add2(func *funcptr){
    return funcptr(2,3);
}

func *factory(int n){
    printf("got params:%i\n",n);
    return add;
}

int main(){
    func *funcptr = factory(5); 
    printf("%i\n",funcptr(1,2));
}

https://godbolt.org/z/zj4Yax

0___________
  • 60,014
  • 4
  • 34
  • 74
  • 1
    @RobertHarvey *`you obfuscate your`* you are just not familiar with this form. – 0___________ Aug 04 '20 at 23:58
  • I don't think it's clearer at all. That typedef will only work with a function taking two int parameters, and there's nothing in the typedef'd name that would suggest this. – Robert Harvey Aug 05 '20 at 00:06
  • @RobertHarvey I do not understand you comment. I believe that is related to my previous comment. Functions always (except some weird `int f() ...` take well defined number of parameters (even variadic functions which are well defined). If you need another - define another function type. – 0___________ Aug 05 '20 at 00:13
  • [ shrug ] Function pointers aren't *that* hard to understand that you need to typedef them to make them "simpler." – Robert Harvey Aug 05 '20 at 00:15
  • @RobertHarvey sure this is a perfect example of the "not obfuscating" "plain" function pointer syntax : `int (*(*func[5])(float, int (*)()))(int);` very easy to humans for sure – 0___________ Aug 05 '20 at 00:20
  • even `cdecl` has a problem to translate it to English. But it is the correct C code : https://godbolt.org/z/qfM8nf – 0___________ Aug 05 '20 at 00:31
0

Here is your solution:

#include <stdio.h> 
// A normal function with an int parameter 
// and void return type 
void p(int a) 
{ 
    printf("Value of a is %d\n", a); 
} 
  
int main() 
{ 
    // fun_ptr is a pointer to function p()  
    void (*fun_ptr)(int) = &p; 
  
    /* The above line is equivalent of following two 
       void (*fun_ptr)(int); 
       fun_ptr = &p;  
    */
  
    // Invoking p() using fun_ptr 
    (*fun_ptr)(10); 
  
    return 0; 
} 
0
int *p(int,int) = factory(5); 

This doesn't work because int *p(int,int) here means a function declaration that takes two int and returns a pointer to int. It's similar to when you write int* p(int,int);. It's not a function pointer.

You do need the bracket:

int (*p)(int,int) = factory(5); // this declare `p` as a function pointer, then assign it to `factory` function.
artm
  • 17,291
  • 6
  • 38
  • 54
0

A function name is indeed converted to the address of the function, which is why you don't need (but can have) & in return add;.

However, int (*p)(int,int) = factory(5); absolutely does need the first pair of parentheses because otherwise (int *p(int,int)) you're declaring p as a function taking two int and returning a pointer to int, not as a pointer to a function taking two ints and returning int.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142