Tinkidinki Tinkidinki - 6 days ago 6
C Question

Use case of function pointers in c

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?

Answer

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.

Comments