[comp.std.c] function returning pointer to itself

olson@batcomputer.UUCP (07/12/88)

Does the new C standard have a natural way to declare a
function that returns a pointer to itself
????

(if you are puzzled by the question, consider the problem 
 of writing a state machine where the states are indicated
 by functions.  To go from one state to another, a function
 exits, returning a pointer to the next function to be executed.
 In the C that I know, I know of no way to declare such functions.
 What does the new standard suggest?)

Todd Olson
olson@helios.tn.cornell.edu
Physics Dept/ Cornell Univ/ Ithaca NY 14853

olson@batcomputer.tn.cornell.edu (olson) (07/13/88)

In article <5485@batcomputer.tn.cornell.edu> olson@tcgould.tn.cornell.edu (olson) writes:
>Does the new C standard have a natural way to declare a
>function that returns a pointer to itself
>????

Thanks to all the people that replied to my question.
Everyone said effectively, "NO, this can not be done NATURALLY in C"
(which is the response I expected)
BUT you can mock it up by
  1) using type cast
  2) encapsulation in a data structure

That C can't do this naturally bugs me.
What do people think of the following proposal?

Define a new primative type  'self'   (not a very good name ...)
  self *p;	means  p points to something that 
                         points to something that ...
                   or  p points to itself
		       p->p->p->p->p->...
  self *f();	means  f is a function returning a pointer to a 
                              function returning a pointer to a ...
                    or f is a function returning a pointer to itself
		       f()->f()->f()->...
  self **f()	means  f is a function returning a pointer to a pointer to a
                              function returning a pointer to a pointer to a ...
                   or  ???
                       f()->p->f()->p->f()->p->...
  self *(*p)() 	means  p is a pointer to a function returning a pointer to a
                              pointer to a function returning a pointer to a ...
		   or  ???
		       p->f()->p->f()->p->f()->...
That is, 'self' sets up a definition that is "solved" by iteration
(but that is NOT how you implement it)
self *(*p)() =>  p=*(*p)() = *(*(*(*p)()))() = ...

Note that   self  must always involve pointers,  self p  is not allowed.

Further one could write
  p->f()->f()->f()->f()->...
as
 typedef self *state();
 state *p;
Without typedefs this would not be possible to express,
unless further syntax modifications were made, such as
  self *<*p>();		means p->f()->f()->f()->...
  self *<f()>;		means f()->p->p->p->...
where the <> indicate the part that is to be iterated on
ie    self *<f()>    =>    <f()>=*<f()>      rather than  f = *<f()>

SIDE ISSUE: (independent of self)
Note in the same way that it is impossible to declare a function
using the typedef
typedef int myfunc();
because 
myfunc f(){};   means   int  (f())(){};
which is illegal,
it is impossible to declare a function
state f(){};
This is something that bugs me too.
Would it screw up the intuitiveness of typedefs too much
to define  myfunc f(){}; to mean  int f(){}; 
since the only other meaning is illegal????????


COMMENTS
1) I don't see how 'self' would pose any implementation problems.
   (on the other hand I have never written a compiler, only thought about it)
2) There have been enough occasions where I could have used this primative
   that I would call it a useful feature.
3) It might be opening a pandora's box.  Consider, someone might say, well
   I want  f()->p->f()->p->p->f()->p->p->p->f()->...
   or one where the number of p's are the digits of PI.
   Well, what can I say.  These would be a lot harder to implement.
   I haven't been able to conceive of a use for them.
4) It is probably to late to add this primative to the new C standard.

Todd Olson
olson@helios.tn.cornell.edu
Physics Dept/ Cornell Univ/ Ithaca NY 14853

jbs@fenchurch.MIT.EDU (Jeff Siegal) (07/13/88)

In article <5485@batcomputer.tn.cornell.edu> olson@tcgould.tn.cornell.edu (olson) writes:
>Does the new C standard have a natural way to declare a
>function that returns a pointer to itself
>????

I'm not sure about a natural way, but the following should suffice:

typedef void *(*NextStateFun)();

static void *state1();
static void *state2();
static void *state3();

void *state1() { return (void *)state2; }
void *state2() { return (void *)state3; }
void *state3() { return NULL; }
void * const initial_state = (void *)state1;
.
.
.
    void *state = initial_state;
  
    while (state) { state = (*(NextStateFun)state)(); }

chris@mimsy.UUCP (Chris Torek) (07/13/88)

In article <9667@eddie.MIT.EDU> jbs@fenchurch.MIT.EDU (Jeff Siegal) writes:
>... the following should suffice:
>
>typedef void *(*NextStateFun)();

No good: the dpANS does not say that data pointers are the same `size'
as function pointers, and indeed, on (e.g.) the Univac 1100 series, as
I understand it, data pointers are 2 words while function pointers are
18 words.  Hence stuffing a function pointer into a data pointer will
lose information.  The dpANS *does* guarantee that pointers to functions
are all the same `size' (I think), so:

	typedef void (*(*NextStateFun)())();

and go from there.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (07/13/88)

In article <5485@batcomputer.tn.cornell.edu> olson@tcgould.tn.cornell.edu (olson) writes:
| Does the new C standard have a natural way to declare a
| function that returns a pointer to itself
| ????

  Three solutions come to mind. The first may only be used if all
procedures are global. This may not always be the case, as you may want
to return pointers to static functions.

int do_state_1(), do_state_2();
int (*foo[])() = {
	do_init(),
	do_state_1,
	do_state_2
};
int next_state = 0;
.
.
	next_state = (*foo[next_state])();

  This can either set the next_state as a global from the procedure, or
an int state may be returned.

method two:

void do_init();
void (*foo)() = do_init;
.
.
	(*foo)();

  And each procedure sets foo to the next state.

method three:

  This is close to what you want, but gives warnings on some compilers.
I would not use it personally for portability reasons.

int (*do_init)();
int (*next_state())();
.
	next_state = (int (*)()) (*next_state)();

  The assumption is that a pointer to a function returning any one thing
looks like a pointer to a function returning some other thing. I can't
think of any reason this wouldn't be true, but I don't trust it.

  I personally like method two best, then one. If you have some old
archives (ie. net.something) I posted my Turing machine in C using a
modified method one and two, where the pointer was pointing a a STATE
struct, gotten by an index.
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs | seismo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

smking@lion.waterloo.edu (Scott M. King) (07/14/88)

In article <5485@batcomputer.tn.cornell.edu> olson@tcgould.tn.cornell.edu (olson) writes:
>Does the new C standard have a natural way to declare a
>function that returns a pointer to itself

	void *(*
main() )()
{
	return main;
}

Ugly eh???
--

Scott M. King

karl@haddock.ISC.COM (Karl Heuer) (07/15/88)

In article <11514@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes:
>The first [of three solutions] may only be used if all procedures are global.

Not true; the same method works with static functions (provided you correctly
forward-declare them as static).

>... method three:
>This is close to what you want, but gives warnings on some compilers.
>I would not use it personally for portability reasons. ...
>The assumption is that a pointer to a function returning any one thing
>looks like a pointer to a function returning some other thing.  I can't
>think of any reason this wouldn't be true, but I don't trust it.

The dpANS guarantees that you can cast function pointers to other function
pointer types and back; as long as you use the "right" type to invoke it.  I
think there was at least one typo in your code fragment, though.  Try this:

	typedef void (*func_t)(void);	/* arbitrary function pointer type */
	func_t do_init(void), do_state_1(void);
	func_t (*next_state)(void) = do_init;

	next_state = (func_t (*)(void))(*next_state)();

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

djones@megatest.UUCP (Dave Jones) (07/17/88)

From article <7725@watdragon.waterloo.edu), by smking@lion.waterloo.edu (Scott M. King):
) In article <5485@batcomputer.tn.cornell.edu) olson@tcgould.tn.cornell.edu (olson) writes:
))Does the new C standard have a natural way to declare a
))function that returns a pointer to itself
)
) void *(*
) main() )()
) {
) 	return main;
) }
) 
) Ugly eh???
) --
) 
) Scott M. King


Ugly? Yes. Correct?  No.  Don't feel too bad, though.

1. C declarators are notoriously archane, and
2. There's no way to do it, anyway.

In the example you give, "main" is declared as 

	a funtion returning a pointer to
	a funtion returning a pointer to
	void

For a funtion to return a pointer to a function declared like main,
it would have to be declared as

	a funtion returning a pointer to
	a funtion returning a pointer to
	a funtion returning a pointer to
	void

You are always going to be off by one level of "pointering".
And what's "void" got to do with anything, anyway?

The problem is that there is no mechanism for forward-referencing
function _types_.  Compare with structure declartions:

	struct foo
	  { struct foo* ref;
	    int bar;
	  };

Here struct foo references its own declaration.  There's no
equivalent mechanism for declarators or typedefs.

The following would work, except for the fact that the basetype
(the first reference to "proc_ptr") is not defined at the point where
it occurs.

	typedef proc_ptr (*proc_ptr)();
                ^^^^^^^^
error: unknown basetype proc_ptr

A neat way to fix it would be to have forward declarations for types:

	typeforward proc_ptr;  /* Declare proc_ptr to be some
			       ** as yet undefined type.
			       */

	typedef proc_ptr (*proc_ptr)(); /* Declare it recursively */

The type-equivalence checker would have to be written correctly, lest
it get into an infinite loop when checking to see if two such types
were equivalent. Notice that in effect, proc_ptr is 

		            a pointer to
	a funtion returning a pointer to
	a funtion returning a pointer to
	a funtion returning a pointer to

		.
		.
		.


That's what you want.  No amount of dereferencing results in "void".



		later,

		Dave J.

smking@lion.waterloo.edu (Scott M. King) (07/17/88)

In article <664@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>From article <7725@watdragon.waterloo.edu), by smking@lion.waterloo.edu (Scott M. King): (me)
>) In article <5485@batcomputer.tn.cornell.edu) olson@tcgould.tn.cornell.edu (olson) writes:
>))Does the new C standard have a natural way to declare a
>))function that returns a pointer to itself
>)
>) void *(*
>) main() )()
>) {
>) 	return main;
>) }
>) 
>) Ugly eh???
>
>Ugly? Yes. Correct?  No.  Don't feel too bad, though.

Oh, don't worry, I don't feel too bad. My declaration *is* correct.
It declares a function returning a pointer to
			a function returning a generic pointer.
However, you could just as easily have any number of levels of indirection
in such a declaration. Ie, the function could be declared as
	a function returning a pointer to
	a function returning a pointer to
	...	(any number of times)
	a function returning a generic pointer (void *)
as in
void *(*(*(*(*(*(*(*(*main())())())())())())())())();

Or, the function could similarly be declared as

	void *
main();

since you can quite easily convert any pointer to a void * and back without
loss of information.
--

Scott M. King

jagardner@watmath.waterloo.edu (Jim Gardner) (07/18/88)

Organization: U. of Waterloo, Ontario
Keywords: 

smking@lion.waterloo.edu (Scott M. King) writes:
 >
 >Oh, don't worry, I don't feel too bad. My declaration *is* correct.
 >It declares a function returning a pointer to
 >			a function returning a generic pointer.
 >[...]
 >since you can quite easily convert any pointer to a void * and back without
 >loss of information.
 
In the January 88 draft, void * is not a completely generic pointer.
It is a generic object pointer, not a function pointer. See pages 23 and 38.
Your declaration is not strictly correct.

smryan@garth.UUCP (Steven Ryan) (07/18/88)

Given C and Unix's disdain for NIH, I suppose I shouldn't say this, but
in Algol 68 it's

         mode yinyang = proc(parameter)yinyang

or

         mode yinyang = proc struct(yinyang value)

---------------------------------------------------------------------
NIH = not invented here

If you're curious about proc struct(...) instead of proc yinyang, it has
to do with wellformed modes--something pascal screws up.

djones@megatest.UUCP (Dave Jones) (07/18/88)

From article <7797@watdragon.waterloo.edu>, by smking@lion.waterloo.edu (Scott M. King):
> In article <664@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>>From article <7725@watdragon.waterloo.edu), by smking@lion.waterloo.edu (Scott M. King): (me)
>>) In article <5485@batcomputer.tn.cornell.edu) olson@tcgould.tn.cornell.edu (olson) writes:
>>))Does the new C standard have a natural way to declare a
>>))function that returns a pointer to itself
>>)
>>) void *(*
>>) main() )()
>>) {
>>) 	return main;
>>) }
>>) 
>>) Ugly eh???
>>
>>Ugly? Yes. Correct?  No.  Don't feel too bad, though.
> 
> Oh, don't worry, I don't feel too bad. My declaration *is* correct.
>
  [Incorrect correctness argument omitted.]
>

At the risk of starting a "'Tis. 'Tain't" kind of argument, I must 
respectfully state "Tain't."

Here's what the Sun3 4.3 C compiler says, yanked dircectly with
the "put" and "get" keys:

"foo.c", line 4: warning: illegal pointer combination

Someone -- I'm regret that I have discarded the letter, and cannot
recall his name -- pointed out that you *can* declare a function that
returns a *structure* containing a pointer to the function, as follows:

typedef struct ugly {
  struct ugly (*pf)();
} fptUG;

fptUG
main()
{
  fptUG retval;
  retval.pf = main;
  return retval;
}


As I pointed out in the first response, the "struct" name-space
is the only one which allows for forward reference.

He said that the above solution was close enough for him.  Well, okay,
I'll go along with it, although I don't know what "struct ugly" has to
do with anything.



			-- Dave J.

bill@proxftl.UUCP (T. William Wells) (07/18/88)

As I recall, the original discussion was on how to create a state
machine using functions for the states.  Anyway, as has been
pointed out, the function can't return a pointer to itself.  What
it can do is to return a structure which contains a pointer to
itself.

The following code compiles and runs fine on our Sun.  It should
also be valid in Standard C.

typedef struct STR {
	struct STR (*func)();
} STR;

STR     Str;

STR     func1();
STR     func2();
STR     func3();

main()
{
	Str.func = func1;
	while (1) {
		Str = (*Str.func)();
	}
}

STR
func1()
{
	STR     str;

	printf("function 1\n");
	str.func = func2;
	return (str);
}

STR
func2()
{
	STR     str;

	printf("function 2\n");
	str.func = func1;
	return (str);
}

STR
func3()
{
	printf("function 3\n");
	exit(0);
}

tps@chem.ucsd.edu (Tom Stockfisch) (07/19/88)

In article <7797@watdragon.waterloo.edu) Scott writes:
)In article <664@goofy.megatest.UUCP) djones@megatest.UUCP (Dave Jones) writes:
))From article <7725@watdragon.waterloo.edu), by smking@lion.waterloo.edu (Scott M. King): (me)
))) In article <5485@batcomputer.tn.cornell.edu) olson@tcgould.tn.cornell.edu (olson) writes:
))))Does the new C standard have a natural way to declare a
))))function that returns a pointer to itself

)Or, the function could similarly be declared as
)
)	void *
)main();
)
)since you can quite easily convert any pointer to a void * and back without
)loss of information.
)Scott M. King

Wrong.  (void *) is guaranteed to hold any _data_ pointer.  I believe you
were correct the first time, as I think (void *(*)()) is guaranteed to
hold any function pointer.  (Anyone care to correct me?)
-- 

|| Tom Stockfisch, UCSD Chemistry	tps@chem.ucsd.edu

rickc@agora.UUCP (Rick Coates) (07/19/88)

In article <5485@batcomputer.tn.cornell.edu>, olson@batcomputer.tn.cornell.edu (olson) writes:
> Does the new C standard have a natural way to declare a
> function that returns a pointer to itself
> ????
> 
(deleted)
(several more articles, with obscure declartions)


Please forgive me if I'm missing something obvious here.....
(I used to be a hardware person - what can I say).

I just tried this out on the only dpANSI compiler I have available -
Microsoft C 5.1 for IBM pc's (this is ironic because I do a lot of work
on a Sun 4 - great machine but no ANSI C; I also work  on Masscomp machines,
which also have no ANSI compiler. When are the Big Boys (medium boys, anyway)
going to support ANSI C?).

This seems to work fine. Compiles with no errors or warnings.

Isn't this a reasonable use of void *   ???
It isn't even Ugly!
-------------program------------
void * test_func();

main()
{
    printf("test: %x\n",test_func);
}

void *
test_func()
{
    return test_func;
}
-------------results-------------

test: 24

---------------------------------

Rick Coates

tektronix!reed!percival!agora!rickc
OR
tektronix!sequent!islabs!ateq!rick

bill@proxftl.UUCP (T. William Wells) (07/19/88)

In article <259@chem.ucsd.EDU> tps@chem.ucsd.edu (Tom Stockfisch) writes:
> Wrong.  (void *) is guaranteed to hold any _data_ pointer.  I believe you
> were correct the first time, as I think (void *(*)()) is guaranteed to
> hold any function pointer.  (Anyone care to correct me?)

1.6
"Object -- a region of data storage in the execution environment,
the contents of which can represent values".

3.1.2.5
"...  and incomplete types (types that describe objects but
lack..."

3.2.2.2
"A pointer to void may be converted to a pointer to any
incomplete or object type.  A pointer to any incomplete or object
type may be converted to a pointer to void and back again; the
result shall compare equal to the original pointer."

However, should you need a generic function pointer:

3.3.4
"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 that has a type that is not
compatible with the type of the called function, the behavior is
undefined."

So, any function pointer type whatsoever can be used as a generic
function pointer.  Just so you cast it back to the original
function type before doing a call with it.

djones@megatest.UUCP (Dave Jones) (07/21/88)

From article <1065@agora.UUCP>, by rickc@agora.UUCP (Rick Coates):
> In article <5485@batcomputer.tn.cornell.edu>, olson@batcomputer.tn.cornell.edu (olson) writes:
>> Does the new C standard have a natural way to declare a
>> function that returns a pointer to itself
>> ????
>> 
> (deleted)
> (several more articles, with obscure declartions)
> 
> Please forgive me if I'm missing something obvious here.....
> (I used to be a hardware person - what can I say).
> 

  You are forgiven.  What can you say?  Well, let's see...
  Say ten _Hail_Richies_ and sin no more.

  There are two problems, really.  One is to declare the thing
  so that it will work on any complying implementation, perhaps
  by resorting to a type-cast.  There have assertions to the effect
  that void* is not castable to a function-pointer and vice versa.
  (Some wierd architectures use different formats for data pointers 
  and function pointers, which again proves that most hardware 
  designers should be in jail.   I'm sure _you_ never did anything like
  that when you were in the hardware game, right?)

  The second problem is actually to make a proper type-declaration --
  by that I mean one which does not require a type-cast.  That can't
  be done.  You can, however, return a structure which contains a
  field pointing to the function, as a couple of correspondants have
  demonstrated.


> I just tried this out on the only dpANSI compiler I have available -
> Microsoft C 5.1 for IBM pc's 

...

> This seems to work fine. Compiles with no errors or warnings.
> 
> Isn't this a reasonable use of void *   ???
> It isn't even Ugly!
> -------------program------------
> void * test_func();
> 
> main()
> {
>     printf("test: %x\n",test_func);
> }
> 
> void *
> test_func()
> {
>     return test_func;
> }
>


I think your compiler is broke.  It is my understanding that it
should warn you that the "return test_func" line does not return a void*.
Here's what the Sun3 compiler says:

   "foo.c", line 11: warning: illegal pointer combination

If your compiler is this lax on pointer types, I would suspect that
it allows some obscure bugs to slip through without warning.


		later,
		Dave J.


P.S.

    I didn't really mean it about the hardware designers belonging in
jail.  I think that a comprehensive work-furlow program with adequate
counciling and group programming support sessions should be the norm
in a modern society.


		D.J.

rickc@agora.UUCP (Rick Coates) (07/24/88)

In article <672@goofy.megatest.UUCP>, djones@megatest.UUCP (Dave Jones) writes:

    (deleted)
>   (Some wierd architectures use different formats for data pointers 
>   and function pointers, which again proves that most hardware 
        ^
  This occurred to me, then I thought, nooooo, no one would do that.

>   designers should be in jail.   I'm sure _you_ never did anything like
>   that when you were in the hardware game, right?)

    Heavens, no! I had a group of software (well, firmware) folks to
    keep me on track!

    (deleted)
>   be done.  You can, however, return a structure which contains a
>   field pointing to the function, as a couple of correspondants have
>   demonstrated.
> 
	Cute. (I haven't seen these responses)
> > Microsoft C 5.1 for IBM pc's 
> 
    (deleted)
> 
> 
> I think your compiler is broke.  It is my understanding that it

  No surprises here!

> should warn you that the "return test_func" line does not return a void*.
> Here's what the Sun3 compiler says:

   Now - my question: (disclaimer first: I am not trying to start a
   'compiler wars' here -  compilers are not standards.  They are,
   however, - in theory - based on standards, and, more importantly,
   they are the only way to _test_ (as opposed to talking about and
   interpreting) standards.  They are also what we have to work with
   every day.)

	As far as I know, Sun does not claim to support the dpANSI
standard, and in fact has not even made any official committment to 
supporting it ever.  Has AT&T said when, if ever, they will support
ANSI C? Any other Unix supplier? Anyone besides the PC world?
Yes, I know that Sun supports many features of dpANSI, but not all
(like function prototyping).

> 
> P.S.
> 
>     I didn't really mean it about the hardware designers belonging in
> jail.  I think that a comprehensive work-furlow program with adequate
> counciling and group programming support sessions should be the norm
> in a modern society.
> 
> 
> 		D.J.

My candidate for Hardware Out Of Control is the IBM EGA/VGA 'standard'.
I can understand ugly choices to keep costs low, but the EGA has lots
of silicon implementing useless functions!  But no support for
drawing lines! Argh.

Just so that Things don't get too out of hand, here: I have plenty of
stories about Software Out Of Control, too.


Rick Coates
Consulting Engineer

tektronix!reed!percival!agora!rickc
OR
tektronix!sequent!islabs!ateq!rick