0

Say I have a function foo() which accepts a pointer to a void function as a parameter.

void foo(void (*bar)(int)) {
    bar(5);
}

If I have a non-void function f(int)

bool f(int i) {
    // ...
    return true;
}

Is there a way to cast f in such a way that it can be passed to foo() without warnings?

My current solution is to define a function void g(int i) {f(i);} and pass g to foo, but this seems inefficient to me. It seems like there should be a way to cast f in such a way that its return value is thrown out.

If this isn't possible, why not?

PGmath
  • 381
  • 3
  • 16
  • Casting function pointers is something [I asked about](https://stackoverflow.com/q/57973305/10871073) a while ago. No proper answer, there, but you may find some of the discussion helpful. – Adrian Mole Sep 17 '20 at 18:38
  • You can cast it and then call resulting pointer, but you will trigger undefined behavior like that because that's what the C standard says, unfortunately. – Petr Skocik Sep 17 '20 at 18:38
  • I would say: if it does need to be portable and you know well the implementation - it is OK. Otherwise no. Example: uC programming. – 0___________ Sep 17 '20 at 18:42
  • 1
    You could make a wrapper function to call your other function. – Christian Gibbons Sep 17 '20 at 18:58
  • 1
    One reason it's not allowed by standard C is that some implementations might use different calling conventions for functions with different return types. Maybe not so many would have a difference between `int` and `void` returns, but for instance, many implementations handle functions returning `struct` types by having a hidden extra argument passing a pointer to the location where the returned value should be stored. If you cast such a function pointer, the function will get called with its arguments out of the expected order and it won't work. – Nate Eldredge Sep 17 '20 at 19:15
  • 1
    @NateEldredge In other words: "if you lie to the compiler, it will get its revenge" /HenrySpencer – wildplasser Sep 17 '20 at 19:48

1 Answers1

0

Sorry if I'm missing the point, but this compiles without warnings with gcc, even with -Wall:

typedef void (*p_bar) (int);

void foo (p_bar bar)
  {
  bar(5);
  }

int f (int i)
  {
  printf ("In f(), arg=%d\n", i);
  return 1;
  }

int main() 
  { 
  foo ((p_bar)f);
  }

I can see why this is a suspicious cast but, in fact, I suspect that it will work fine for integers on most modern compilers. Integers are nearly always returned in a register.

But, as I say, maybe I'm missing something.

Kevin Boone
  • 4,092
  • 1
  • 11
  • 15
  • Ah, that worked. I tried a few different syntaxes but didn't think of `typedef`ing it. In fact I've never seen this syntax for `typedef`ing a function pointer. – PGmath Sep 17 '20 at 19:32
  • 1
    To be honest, I don't think I've ever used a function pointer _without_ a `typedef` the syntax is so ungainly. – Kevin Boone Sep 17 '20 at 19:33
  • 1
    Evne though this appears to work it is very dangerous since it triggers undefined behavior. Your example with `void g(int i) { f(i); }` is actually not as bad as you might think because any decent compiler will optimize away that function call – jo-art Sep 17 '20 at 21:04
  • 1
    I never claimed that it was safe, or reliable, only that it compiled without warnings, which is what the OP was asking for. Any time you cast anything to anything else, you're deciding that you know what you want better than the compiler does. – Kevin Boone Sep 18 '20 at 06:08