[net.unix] functions returning pointers to functions

john@genrad.UUCP (John Nelson) (12/13/83)

I believe that the easiest way to get around the problem is to use
a typedef:

typedef int (*FUNCTION)();

then you can declare the function returning a pointer to function as:

FUNCTION getroutine(name, table)

This SHOULD work with all K&R C compilers

bradn@hammer.UUCP (Brad Needham) (12/14/83)

I think your confusion comes from the two ways of declaring a function:
	1) with other declarations
	2) with the function definition (i.e. the code for the function).
Formal parameters do not appear when you declare a function separately
from its definition, e.g.
	int *a();
vs
	int *a(x)
	int x;
	{
		...
	}
If you want a function returning a pointer to a function returning an int,
you can say it two ways:
	1) as a declaration:
		int (*getroutine())();
	2) or as a declaration and definition:
		int (*getroutine(name,table))()
		char *name;
		struct atable *table;
		{
			...
		}

Because the declaration of functions is so confusing, Graham Ross of Tektronix,
MDP wrote a program to convert between English and C declarations.  He posted
it to net.sources quite a while ago, but I'm sure he can get a copy to you.
He is tektronix!tekmdp!grahamr.

Brad Needham
Tektronix, ECS.
..decvax!tektronix!tekecs!bradn

stevesu@azure.UUCP (Steve Summit) (12/14/83)

Thanks to those who responded.  I now know that the correct
declaration is

		int (*getroutine(name,table))()

and not the

		int (*getroutine))((name,table)

that I had been trying to use.  The astonishing thing is that the
pdp11 compilers I have used (2.8bsd, V7, and sysIII based) accept
either declaration and generate identical (working) code.

                                         Steve Summit
                                         tektronix!tekmdp!stevesu

garys@bunkerb.UUCP (Gary Samuelson) (12/14/83)

In reply to Steve Summit, who wanted a function returning a
pointer to a function returning an integer:

I tried to write this reply in the same style as your request,
but I guess I don't speak King James English well enough.  Will
Today's English suffice :-) ?

Using a typedef divides the declaration into bite-sized pieces,
which the compiler can swallow.

The following program, which I have compiled and run on our VAX
(4.1BSD), contains such a function.  Simply tear along the dotted
line.

Gary Samuelson
decvax!ittvax!bunker!bunkerb!garys
-------------------------------------------------
/*
 * a couple of functions which return integers
 */

int g( x )
int x;
{
	return( x + x );
}

int h( x )
int x;
{
	return( x * x );
}

/*
 * A function which returns a pointer to a function
 * which returns an integer.
 */

typedef int (*ifp)() ;
ifp f( a )
int a;
{
if( a == 0 )
	return( g );
else
	return( h );
}

main()
{
	printf( "%d\n", ((*f)( 0 )) ( 4 ) );
	printf( "%d\n", ((*f)( 1 )) ( 4 ) );
}

stevesu@azure.UUCP (Steve Summit) (12/15/83)

-----------
Crud.  It's been pointed out that I said that

		int (*getroutine))((name,table)

is, amazingly, acceptable to the pdp11 compilers.  That would be
pretty amazing.  What I meant to say was that

		int (*getroutine())(name,table)

is acceptable as well as

		int (*getroutine(name,table))()

which is correct.

Sorry 'bout that.
                                                Steve Summit

kissell@flairvax.UUCP (Kevin Kissell) (12/15/83)

To declare a function returning a pointer to a function returning an
integer, the construct

int (*funcfunc())()

is pretty standard.  Things get confusing when the parameters are added.
Steve's example of the form

	int (*getroutine())(name, table)

does indeed fail under 4.1, but

	int (*getroutine(name, table))()

will work just fine, and is more correct if you think about it.
What I can't figure is how the first version worked under 2.8!

		Kevin D. Kissell
		Fairchild Research Center
		Advanced Processor Development
		uucp:{ucbvax!sun decvax allegra}!decwrl!flairvax!kissell

dmmartindale@watrose.UUCP (Dave Martindale) (12/18/83)

The declaration
	int (*getroutine(name,table))()
declares a function of two arguments which returns a pointer to a function
(taking an unknown number of arguments) which returns an integer.

At first glance, I would expect that the declaration
	int (*getroutine())(name,table))
would declare a routine of zero arguments which returns a pointer to
a function of two arguments which returns an integer.
But in a declaration of a function, you declare only the parameters to
that function, not the parameters which would be passed to any function
to which this function may return a pointer.  So the declaration should
read
	int (*getroutine())()
if getroutine takes no arguments, regardless of what sort of arguments
the pointed-to function wants.

All of the above applies to the actual function definition.  In an
external declaration, no arguments to any of the functions are specified,
and you would use
	int (*getroutine())();
for both of the cases discussed.

IF C were a language in which the types of arguments were checked and
type conversion done automatically, you would see declarations like

	int (*getroutine(name,table))(value,new,old)
	char *name;
	struct tab *table;
	int value;
	struct entry *new, **old;

where the arguments of both getroutine itself and the routine it returns
must be declared.  But it isn't - you're responsible for getting the
number and types of arguments correct yourself.  And since you're not
even syntactically allowed to put in the "extra" information about
the arguments of the returned routine, there isn't anything for lint
to check your code against.  Caveat programmer.

	Dave Martindale

gwyn%brl-vld@sri-unix.UUCP (12/18/83)

From:      Doug Gwyn (VLD/VMB) <gwyn@brl-vld>

This is nearly the first time I've seen PCC do better than the Ritchie
C compiler.
	int (*g())(n,t) {}
generates a "syntax error" message in UNIX System V PCC, as it should.