-1

Can anyone help me explain why the below code works.

Why line func = foo is valid.

typedef int (* fx) (int *fy());
unsigned int foo(void);

int main()
{
    fx func;
    func = foo;
    func(&foo);
    return 0;
}

unsigned int foo(void)
{
    printf("Done!");
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Trong Ho
  • 1
  • 1
  • 3
    The code is _not_ valid. – ad absurdum Dec 08 '18 at 01:36
  • The argument is a function that returns a pointer to int, not a pointer to function. Try something like `typedef int (* fx) (int (*)(void));` – rcgldr Dec 08 '18 at 01:41
  • but it's just _sort of_ valid. An **unsigned int** is not an **int**. – Ted Lyngmo Dec 08 '18 at 01:44
  • 2
    Note that the typedef has a non-prototype function as the argument to the function pointer type — the `int *fy()` should be `int *fy(void)` if you want to specify a function (pointer) that takes no arguments. In this context, the 'function returning `int *` is turned into 'pointer to function returning `int *`, but that is better written as `int *(*fy)(void)` — or whatever argument list you want. If you don't want it to be a function returning a pointer to `int`, drop the first (only) star. – Jonathan Leffler Dec 08 '18 at 01:46
  • 2
    C11 [§6.3.2.3 Pointers ¶8](http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p8) says: _A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined._ Be careful about casting function pointers to a different type and then having it called it with a different signature (for example, a comparator passed to `bsearch()` or `qsort()`); you get undefined behaviour! – Jonathan Leffler Dec 08 '18 at 01:55
  • 1
    You might find [Understanding typedefs for function pointers in C](https://stackoverflow.com/a/1591492/15168) useful. – Jonathan Leffler Dec 08 '18 at 02:00

1 Answers1

1

Does this make sense?

#include <stdio.h>
typedef int (*fx)(void); // fx is defined as a type of function that returns an int and takes no arguments

int foo(void) {
    printf("Done!");
    // "control reaches end of non-void function"
}

int main() {
    fx func;
    func = foo;
    //func(&foo);
    func();
    return 0;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • 1
    No; that typedef (`typedef int (*fx)();`) does not specify that the function takes no arguments. It specifies that the function takes an undefined set of arguments — but it isn't a variadic function (whose prototype should end `, ...)`) because those must have a full prototype in scope. If you want 'no arguments', write `typedef int (*fx)(void);`. – Jonathan Leffler Dec 08 '18 at 01:58
  • 1
    Thank you for fixing that. I'm going to leave my previous comment in place as it is self-contained and may help people. I'll remove this shortly. (It wasn't my DV either.) You could use `return printf("Done!\n");` to return a value from the function. If you wanted to, you could observe that `(*func)();` uses the 'declaration matches use' theme that was a part of C's design. Mostly, only old fogeys like me still use that notation, though I still think it is clearer that you're using a pointer to function when written like that. This comment has a limited life; I shall remove it soon. – Jonathan Leffler Dec 08 '18 at 02:04
  • Thanks, i took the code as it was but have added the `void` in the declaration to match the definition. Cheers! I left the comment in the function there instead of inventing a return on purpose. I thought it would help OP. – Ted Lyngmo Dec 08 '18 at 02:05