Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typedef function pointer, for a function that returns a pointer to a function of its own type? [duplicate]

Tags:

c

That was a mouthful. Essentially I have this:

typedef int (*decker_function_t)(int);

decker_function_t decker;
// Some logic making decker point to a real function
int i = decker(5);

return 1;

However, what I really want is for functions of type decker_function_t to return a type of decker_function_t, rather than an int. I cannot figure out how to make a typedef self-referential. Is this possible?

Also please note I am asking strictly for C, not C++,

like image 986
Adam S Avatar asked Nov 15 '13 22:11

Adam S


2 Answers

It is not possible to declare it directly. The language syntax does not offer the opportunity to break the infinite declarative recursion inherently present in this declaration, which is a pity, since there's no physical recursion in it.

The workarounds would include

  1. Using a "generic" function pointer type void (*)(void) for the return type. Of course, you will have to cast the returned value to the desired specific function type. This is what is usually suggested as "use void *" solution, except that void * is not the right way to go about it (formally data pointer types are not interconvertible with function pointer types).

  2. Using a wrapper struct type as a middle-man. The language allows referring to struct type from the declaration of the very same struct type in a number of contexts. In a way, that is a supported form of "infinite declarative recursion". By taking advantage of this one can do

    struct fptr_struct {
      struct fptr_struct (*fptr)(int);
    };
    

    and declare such functions as returning struct fptr_struct type. This will also require some insignificant syntactic efforts to obtain the returned pointer, i.e. access to the nested fptr field, but at least it does not require a cast.

like image 113
AnT Avatar answered Oct 19 '22 10:10

AnT


Following from the function returning itself SO; its possible to return a dummy function pointer which can then be properly cast.

This avoids using a void * and non-standard casting. So it can't return itself, but is able to return a dummy fp and can be handled by convention:

#include <stdio.h>
typedef int (*dummy_function_type)(int);

typedef dummy_function_type (*decker_function_t)(int);

dummy_function_type some_task(int someparam)
{
  /* do some work.. */
  fprintf(stdout, "%s\n", __FUNCTION__); //gcc specific
  return 0;
}

dummy_function_type decker_queue_root(int redundantparam)
{
  /* do some work.. */
  fprintf(stdout, "%s\n", __FUNCTION__); //gcc specific
  return (dummy_function_type)some_task;
}

void process_decker_queue(decker_function_t jobs)
{
  /* nonstandard gcc function nesting follows */
  decker_function_t next_decker(decker_function_t cur_decker, int param)
  {
    if(!cur_decker)return 0;
    return (decker_function_t)(cur_decker(param));
  }

  decker_function_t cursor;
  cursor = jobs;
  while(cursor)
  {
    cursor = next_decker(cursor, 0); //param seems pretty redundant in this context..
  }
}

int main()
{
  //work queue stack
  decker_function_t prime = &decker_queue_root;
  process_decker_queue(prime);
  fprintf(stdout, "this compiles..\n");
  return 0;
}

This gives the following output:

$ ./test_frecurse 
decker_queue_root
some_task
this compiles..

But it would be simpler to just have a list of jobs and call them in order

like image 1
amdixon Avatar answered Oct 19 '22 11:10

amdixon