Nova Shadowflame
Nova Shadowflame

Reputation: 194

C Function Pointer Differences

I have the following C Code:

#include <stdio.h>

int max(int x, int y, int (*compare)(int, int))
{
  return (*compare)(x,y) ? x : y;
}

int greater_than(int x, int y)
{
  if(x > y) return 1;
  else return 0;
}

int main(void) {
 printf("%d",max(6,7,greater_than));
}

It's just there to test function pointers. But the code still works the same even if i dont use int (*compare)(int,int) but int compare(int,int). It also works if I don't dereference the function pointer or if use int compare(int,int) but still dereference. It also doesn't make a difference if I pass greater_than or &greater_than. Why is this?

With regards Nova

Upvotes: 1

Views: 298

Answers (2)

LIH
LIH

Reputation: 36

Great answer given by Lundin before. Rep too low to comment, so I'll put this here as extra. I saw the link on a similar post here on stackoverflow, I liked the tutorial.

Origin of link to tutorial is this question: How do you pass a function as a parameter in C?

Function pointer tutorial mentioned in the above: http://www.newty.de/fpt/index.html

Hope I'm not being presumptuous, I liked it, maybe it will make for a pleasant read for you as well.

Upvotes: 0

Lundin
Lundin

Reputation: 213842

These 2 versions are equivalent:

  • int max(int x, int y, int (*compare)(int, int))
  • int max(int x, int y, int compare(int, int))

Just like arrays passed as parameters to functions "decay" into pointers to the first element, similar "decay" happens to functions. They decay into function pointers. The standard says

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

So the second (obscure) version above gets silently translated by the compiler into the first version. But there is never a reason to declare a function inside a parameter list, so this whole issue is quite exotic.


As for why compare(x,y) works as fine as (*compare)(x,y) or for that matter (*****compare)(x,y), it is because whenever you use either a function name or function pointer, you always get a function pointer. If you try to de-reference the function pointer, you get the function. Which again bounces back implicitly into a function pointer.

See Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?


Beginners and veterans all alike can safely forget about the above obscure rules, and just do this:

int max(int x, int y, int (*compare)(int, int))
{
  return compare(x,y) ? x : y;
}

Or better yet, use typedef:

typedef int compare_t (int, int);

...

int max(int x, int y, compare_t* compare)
{
  return compare(x,y) ? x : y;
}

Upvotes: 4

Related Questions