0

One of the common use cases I've come across when I read about function pointers is that they can be used to make a function more flexible, as part of the functionality of the function can be taken in as a parameter. An example for this is qsort where I can make a compare function to decide what is meant by greater and lesser (ascending, descending, is a multiple of,etc) and pass the compare funtion pointer to qsort function.

Here, the function repeat has addptr as parameter and therefore performs multiplication.

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

int (*addptr)(int,int);

int repeat(int a,int b,int (*funcptr)(int,int))
{
    int i,ans=0;
    for(i=0;i<a;i++)
    {
        ans=(*funcptr)(ans,b);
    }
    return ans;
}


int main()
{
    addptr=&add;
    printf("%d\n",repeat(7,5,addptr));  

    return 0;

}

But the same exact thing can be done without function pointers at all!

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


    int repeat(int a,int b,int func(int,int))
    {
        int i,ans=0;
        for(i=0;i<a;i++)
        {
            ans=func(ans,b);
        }
        return ans;
    }


    int main()
    {
        printf("%d\n",repeat(7,5,add)); 

        return 0;

    }

So why is this even one of the uses of function pointers? What is the advantage of the first code over the second?

5
  • 3
    "Function type" decays to "function pointer type" in function parameters Commented Nov 28, 2016 at 8:23
  • What is the advantage of the first code over the second? You need to find use cases that apply to that. That's a very broad scenario, IMHO. Commented Nov 28, 2016 at 8:24
  • 2
    You are doing the same thing in both Commented Nov 28, 2016 at 8:24
  • If your use is fixed, you don't need function pointers. If your use is variable or can change (in design) over time, you may consider it. Commented Nov 28, 2016 at 8:26
  • Function pointers allow passing functions as parameters (aka first-class functions). I think the best way to understand the power of passing functions as parameters (function composition, closures, etc...) is to try some functional language, it will give you a good insight about why there are function pointers. Commented Nov 28, 2016 at 10:52

3 Answers 3

5

There is a rule C11 6.7.6.3/8 saying that if you write a function inside a parameter list, it will get adjusted to a pointer to function of that type:

A declaration of a parameter as ‘‘function returning type’’ shall be adjusted to ‘‘pointer to function returning type’’,

This works similar to when you write an array as function parameter, it gets adjusted to a pointer to the first element.

That being said, it is not really meaningful to write a function as a parameter, it is just very confusing to the reader. Use function pointers instead.


EDIT

For maximum readability, I would personally recommend using this style:

typedef int operation_t (int, int);

int repeat (int a, int b, operation_t* operation)
{ ...

Though the most commonly used style is perhaps this one:

typedef int (*operation_t) (int, int);

int repeat (int a, int b, operation_t operation)
{ ...

I prefer the former since hiding pointers behind typedefs is a bad idea, and since that style makes function pointers consistent with regular pointers.

Sign up to request clarification or add additional context in comments.

4 Comments

So, here internally, add and func are the same as addptr and funcptr?
It is purely syntactic sugar. Many (myself included) find it easier to read the code if you use the function syntax.
Readability is a poor argument though, since the most readable form uses a typedef. I added some examples to the answer.
0

As noticed in comment by @user2390668, func in repeat in already a function pointer. And when you call it, add decays to a function pointer.

If your question is what is a possible use case for a variable holding a function pointer, we must try to imagine a use case where a function will not only be passed as a parameter, but will have to be stored. An example for that would be simulating polymorphism of structs in C. Here is an oversimplified example:

#include <stdio.h>

struct Base {
    /* common member variables
    ...
    */
    const char *name;
    void (*display)(void *, FILE *fd);
};

struct S1 {
    struct Base base;
    /* other member variables */
};

void _S1_display(void *this, FILE *fd) {
    struct S1 *s1 = this;
    fprintf(fd, "In S1, name: %s\n", s1->base.name);
}

struct S2 {
    struct Base base;
    /* other member variables */
};

void _S2_display(void *this, FILE *fd) {
    struct S2 *s2 = this;
    fprintf(fd, "In S1, name: %s\n", s2->base.name);
}

void process(void *this, FILE *fd) {
    struct Base *base = this; /* valid because base is first element of both S1 and S2 */
    base->display(this, fd);
}

int main() {
    struct S1 s1 = { "s1", &_S1_display };
    struct S2 s2 = { "s2", &_S2_display };

    process(&s1, stdout);
    process(&s2, stdout);
    return 0;
}

Ok, fur such a simply example, polymorphism would not be necessary, but as I said it is oversimplified...

Comments

0

You may use pointers to functions when you need a little more abstraction. For example, you may want to manage a table of operators that a generic function should use:

int add(int a, int b) {
    return a+b;
}
int sub(int a, int b) {
    return a-b;
}
int mult(int a, int b) {
    return a*b;
}
int div(int a, int b) {
    return a/b;
}

void doit(int a,int b,int (*ptr[2])(int,int)) {
    printf("%d\n",ptr[0](a,b));
    printf("%d\n",ptr[1](a,b));
}


int main() {
    int (*ptr[2])(int,int);
    printf("additives (1) or multiplicatives (2) ?");
    int choice;
    scanf("%d",&choice);

    switch(choice) {
        case 1:
          ptr[0] = &add;
          ptr[1] = &sub;
          break;
        default:
          ptr[0] = &mult;
          ptr[1] = &div;
          break;
    }
    doit(7,5,ptr);
    return 0;
}

Of course you can also design a doit function with two pointers but sometimes a table is more convenient (think about a variable length table of function pointers for example, I know even in this case we may use a variable arguments list...).

At least, passing a function pointer in parameter is defining a function pointer variable...

Another example is also implementing in C object oriented programming, where you may implement methods as function pointers members.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.