skip to Main Content

I am trying to familiarize myself with pointers to functions in C. I have looked online and found several examples of these. However, when I compile my program (using GCC [version (Debian 12.2.0-14) 12.2.0]), I get several errors even though my code has an almost identical structure to that shown in the online examples.

For example, at How do function pointers in C work? we have the following.

Passing the pointer to another function is basically the same:

int add2to3(int (*functionPtr)(int, int)) {
    return (*functionPtr)(2, 3);
}

Whereas in my code I have the following function prototype. The numbers at the beginnings of lines refer to the line numbers in my code and help when referring to the error messages generated by GCC.

28 double array_op(double array[], size_t size, double (*pfun)(double, double));

The corresponding function call is as follows.

54 result = array_op(values, numberOfElements, (*pfun)(a, b)); // Calculate the sum

When I compile the program, this function call causes GCC to generate the following error message.

ex9_2.c: In function ‘main’:
ex9_2.c:54:49: error: incompatible type for argument 3 of ‘array_op’
   54 |    result = array_op(values, numberOfElements, (*pfun)(a, b)); // Calculate the sum
      |                                                ~^~~~~~~~~~~~
      |                                                 |
      |                                                 double
ex9_2.c:28:55: note: expected ‘double (*)(double,  double)’ but argument is of type ‘double’
   28 | double array_op(double array[], size_t size, double (*pfun)(double, double));
      |                                              ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~

In line 54 I have varied the form of the function pointer using, in turn, the form shown above, as well as (pfun)(a, b), *pfun(a, b), and pfun(a, b). All of these forms have resulted in the error message shown above.

My understanding is that the address of a primitive function (add(), subtract(), multiply()) is passed into function array_op() through pfun and that this is what causes each of the primitive functions to be applied, in turn, to pairs of elements from array values[]. As my usage of the function pointer has a very(!) similar structure to that shown in the stackoverflow example, I am at a loss to understand where I have gone wrong.

Given that this is my first time using function pointers, this is perhaps not surprising.

Could someone please help clarify my understanding so that I can correct my code?

2

Answers


  1. In result = array_op(values, numberOfElements, (*pfun)(a, b));, (*pfun)(a, b) is not a pointer to a function. It is a call to a function. The correct code is result = array_op(values, numberOfElements, pfun);.

    Putting arguments in parentheses after an expression forms a function call. So:

    • pfun is a pointer to a function.
    • *pfun designates that function.
    • (*pfun) is the same thing, with grouping.
    • (*pfun)(a, b) is a call to the function.

    Given some pointer p to a function, p is the pointer, and (*p)(…) is a call to the function. The result of a call to the function is a value of the type returned by the function.

    Also, you do not need to use * to call a function. The function call operator actually takes a pointer to a function, so pfun(a, b) is a correct function call. In (*pfun)(a, b), the expression (*pfun) is automatically converted from the function back to a pointer to a function. In fact, if you write (**pfun)(a, b), the *pfun will be converted to a pointer, then * produces the function is points to, and then that is also automatically converted to a pointer. This can continue indefinitely; (*****pfun)(a, b) will end up being just pfun(a, b).

    Login or Signup to reply.
  2. An addition to @Eric’s answer here you have an example:

    int add(int x, int y)
    {
        printf("Func: %s ", __FUNCTION__);
        return x + y;
    }
    
    int sub(int x, int y)
    {
        printf("Func: %s ", __FUNCTION__);
        return x - y;
    }
    
    int mul(int x, int y)
    {
        printf("Func: %s ", __FUNCTION__);
        return x * y;
    }
    
    int divi(int x, int y)
    {
        printf("Func: %s ", __FUNCTION__);
        int result = 0;
        if(y) result = x / y;
        return result;
    }
    
    int doSomething(int x, int y, int (*f)(int, int))
    {
        return f(x,y);
    }
    
    int main(void)
    {
        int (*func[])(int, int) = {add, sub, mul, divi};
        int x,y;
        srand(time(NULL));
    
        for(int i = 0; i < 10; i++)
        {
            x = rand(); y = rand();
            printf("%d %d %dn", x, y, doSomething(x, y, func[rand() % (sizeof(func) / sizeof(func[0]))]));
        }
    }
    

    https://godbolt.org/z/fvE9zY8P4

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search