#include <stdio.h>

/* Passing a function to itself */

/* Example 1 */

/* Choose a return type */
typedef int example1_t;

/* Establish a function type with no parameter specification */
typedef example1_t f_example1_any();

/* Establish the actual function type */
typedef example1_t f_example1(f_example1_any *, int, double);

/* You can declare the upcoming function */
f_example1 example1;

/* Definition */
example1_t example1(f_example1_any * f, int i, double d) {
    /* Convert 'f' to the actual type */
    f_example1 * func = f;

    (void) i;
    (void) d;
    /* Simple check */
    if (func == example1) {
        puts("example1: Passed ourself in the street");
      }
    return 0;
  }

/* Example 2 */

/* Choose a _unique_ return type */
typedef struct { int ret; } example2_t;

/* Establish a function type with no parameter specification */
typedef example2_t f_example2_any();

/* Establish the actual function type */
typedef example2_t f_example2(f_example2_any *, int, double);

/* You can declare the upcoming function */
f_example2 example2;

/* Definition */
example2_t example2(f_example2_any * f, int i, double d) {
    example2_t result;
    /* Convert 'f' to the actual type */
    f_example2 * func = f;

    (void) i;
    (void) d;
    /* Simple check */
    if (func == example2) {
        puts("example2: Passed ourself in the street");
      }
    return (result.ret = 0), result;
  }

/* Example 3 */

/* Use a function pointer wrapper */
typedef struct s_example3 s_example3;

/* Establish the actual function type */
typedef int f_example3(s_example3 *, int, double);

/* Complete the object type */
struct s_example3 {
    f_example3 * func;
  };

/* You can declare the upcoming function */
f_example3 example3;

/* Definition */
int example3(s_example3 * f, int i, double d) {

    (void) i;
    (void) d;
    /* Simple check */
    if (f->func == example3) {
        puts("example3: Passed ourself in the street");
      }
    return 0;
  }

/* Tests */
int main(void) {
    s_example3 example3_wrapper = { example3 };

    example1(example1, 42, 3.14159);
    example2(example2, 42, 3.14159);
    example3(&example3_wrapper, 42, 3.14159);

    return 0;
  }