[net.unix] functions returning pionters to functions

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

And it came to pass that I desired to code a function returning a
pointer to a function returning an integer, and with good reason,
for it was not a hack; and I was distressed, for I was unsure as
to what form the incantation should take, but I crossed my
fingers, and I did guess, and I did type

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

for the name of the routine was getroutine, and its arguments
were name and table; and I did luck out, for the compiler was
pleased, and it did emit code, and the code did run, for this was
a lowly 11, running 2.8bsd, and some things were easier then.

And the program was good, and it went forth, and multiplied, and
it came to pass, that I desired to compile it again, on a vax
under 4.1 .

And the compiler did puke, and it did shout syntax error, for it
did consider my incantation a blasphemy; and not recognizing the
declaration of a function, it did consider the rest of my file to
be in error as well.

And I did repent, for I had used the heathen method of trial and
error, and although I had skirted the first trial, I had been
eventually judged to be in error.  

And I sought comfort in the scriptures, and I consulted the Book
of Brian and Dennis, as I should have done in the first place,
and in chapter 5, on page 116, I did read, that the declarations
should be studied with some care, and I did study, with some
care; but the example given was merely a pointer to a function,
and not the function returning the same, that I desired.

And as I studied the example, I did reason that if

	int *a

was the declaration for a pointer to an integer and

	int *a(x)

was the declaration for a function of x returning a pointer to 
an integer; then if

	int (*a)()

was the declaration for a pointer to a function returning an
integer, then surely

	int (*a)()(x)

should be the declaration for a function of x returning a pointer
to a function returning an integer, and this did I try, but still
was the compiler displeased, and I did reason that perhaps
another level of parenthesis might be required, as in

	(int (*a)())(x)

or perhaps

	((int)(*a)())(x)

and these too did I try, but still was the compiler displeased,
and still did it continue to pass numerous judjements on my
program, beginning with "syntax error" on the afflicted line, and
continuing with others too numerous to mention.

And I did realize, that I was again regressing into the accursed
method of trial and error, and that along that path surely did
not lie salvation, and so now do I beseech you, my brothers and
sisters on the net, and fellow supplicants of unix, to guide me
if you can, out of my darkness and into the light, that I might
declare a function returning a pointer to a function returning an
integer, in a way equally blessed under the deities of 2.8 and
4.1 .

                                         Steve Summit
                                         tektronix!tekmdp!stevesu

P.S.  And it came to pass, that I recieved many flames, as if
directly from the gates of Hell, for the net was not amused, and
it did suggest that I should have submitted my beseechment to
net.religion, or /dev/null; and if this be the case, then I
apologize, but I am in a curious mood today, and ask forgiveness,
for I know not what I do.

ark@rabbit.UUCP (12/14/83)

Suppose I want to write a function f that returns a pointer to a
function returning an integer.  I first think about how I'm going to
invoke it.

	f(x)

is going to be a pointer to a function, so

	*f(x)

will be this function itself.  Well, since * binds less tightly than
function calls, I must invoke the (secondary) function by saying

	(*f(x))()

and this expression is now an integer.   If I want to write f, I therefore
say:

	inf (*f(x))()
		int x;
	{
		...
	}

Works like a charm.

djh@ccivax.UUCP (12/15/83)

	The declaration 'int (*ptr)()' defines 'ptr' as a pointer to
	an integer function. What you want to do is replace 'ptr' with
	your function definition of 'getroutine(name, table)', thus
	giving 'int (*(getroutine(name, table)))()' which defines
	getroutine as a function with two arguements which returns a
	pointer to an integer function (or function that returns an 
	integer).
	
	Note that 'ptr' was replaced by '(getroutine(name, table))'.
	The enclosing parenthesis are necessary to bind the arguements
	to getroutine before the * (pointer binding) is applied.
	
	Following is a sample program and execution printout.

/*
 *	functest.c	program to test functions that return pointers
 *			to other functions.
 */

int a()		/* define integer function a */
{
	printf("In function 'a'\n");
	return(1);
}

int b()		/* define integer function b */
{
	printf("In function 'b'\n");
	return(2);
}

int c()		/* define integer function c */
{
	printf("In function 'c'\n");
	return(3);
}

int (*(func(arg)))()	/* define function func which returns */
int arg;		/* an integer function pointer */
{
	switch(arg) {
	case 1:
		return(a);

	case 2:
		return(b);

	case 3:
		return(c);
	}
}

main()
{
	int (*ptr)();	/* ptr is pointer to integer function */

	ptr = func(3);
	printf("Returned %d\n",(*ptr)());

	ptr = func(1);
	printf("Returned %d\n",(*ptr)());

	/* ptr = func(2); test without intermediate step */
	printf("Returned %d\n",(*(func(2)))());
}

	Sample Execution:

In function 'c'
Returned 3
In function 'a'
Returned 1
In function 'b'
Returned 2

	Dan Hazekamp
	Computer Consoles Inc.
	Rochester N.Y.

	{siesmo,allegra}!rochester!ccivax!djh

stevens@inuxh.UUCP (12/16/83)

>	The declaration 'int (*ptr)()' defines 'ptr' as a pointer to
>	an integer function. What you want to do is replace 'ptr' with
>	your function definition of 'getroutine(name, table)', thus
>	giving 'int (*(getroutine(name, table)))()' which defines
>	getroutine as a function with two arguements which returns a
>	pointer to an integer function (or function that returns an 
>	integer).
>
>	Note that 'ptr' was replaced by '(getroutine(name, table))'.
>	The enclosing parenthesis are necessary to bind the arguements
>	to getroutine before the * (pointer binding) is applied.

No, the parentheses around '(getroutine(name, table))' are not required.
function arguments `()' bind more tightly than pointer dereferencing `*'.
(K & R, p. 49 [the page my K & R falls open to]).

--
Scott Stevens
AT&T Consumer Products Laboratories
Indianapolis, Indiana
UUCP: inuxh!stevens

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

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

In C, * binds weaker than func() so parentheses are NOT necessary in
	*func()
if you want to call the function, then dereference the return value.