[comp.lang.c] help with declaration

atc@ut-sally.UUCP (Alvin T. Campbell III) (06/17/87)

	I have a question for all you C wizards out there. I want to write 
a function which returns a pointer to another function. I checked Kernighan
& Ritchie and Harbison & Steele, but found no solution.

	My specific application is that I am writing a program which uses 
menus. Each menu item has an associated function which should be called 
when that item is selected. I want to write a function which puts a menu
on the screen, lets the user select an item, and then returns the appropriate
function.

	I want to structure the code as follows:

#define TRUE	1
main()
{
	int	(*func)();

	while(TRUE)
	{
		func = getmenu();
		(*func)();
	}
}

	So how do I declare getmenu() ?

	I am writing the code on a Silicon Graphics, Inc. IRIS 2400,
whose flavor of UNIX is System V with Berkeley Enhancements. The vendor
has a hotline for questions, so I called there first. I was referred to 
someone in their compiler group. He told me to just declare getmenu()
as an integer function, since it would work in this case. I am a 
purist, so I found this suggestion disgusting.

	By the way, please don't suggest that I restructure my code
to avoid the problem. I know there are many ways to do this, and in
fact I have done so already. I am just curious to see how to do it
right.

	Thanks for the help.

				A. T. Campbell
				University of Texas at Austin
				Computer Graphics Lab
				atc@sally.CS.UTEXAS.EDU

edw@ius2.cs.cmu.edu (Eddie Wyatt) (06/18/87)

In article <8286@ut-sally.UUCP>, atc@ut-sally.UUCP (Alvin T. Campbell III) writes:
> 
> 	I have a question for all you C wizards out there. I want to write 
> a function which returns a pointer to another function. I checked Kernighan
> & Ritchie and Harbison & Steele, but found no solution.
> 
> 				A. T. Campbell
> 				University of Texas at Austin
> 				Computer Graphics Lab
> 				atc@sally.CS.UTEXAS.EDU

Syntax is :

		<type> ( * <function_name> ( <parameter_list> ) ) ( )

Example definition for a function that returns a pointer to a function that
returns an int :

int tt();

int (*foobar(x))()
    int x;
    {
    printf("x = %d\n",x);
    return(tt);
    }

int tt() { printf("Hello world\n"); return(1); }

main()
    {
    int (*func)();

    func = foobar(3);
    printf("func returns %d\n",func());
    }
-- 
					Eddie Wyatt

e-mail: edw@ius2.cs.cmu.edu

ark@alice.UUCP (06/18/87)

The problem: how to declare a function that returns a function pointer:

	int (*foo)();
	foo = getfunc();

how to declare getfunc?

Well, let's see: if we call getfunc(), dereference the result,
and call that, we get an int.  In other words,

	(*getfunc())()

is an int, so we should say

	extern int (*getfunc())();

All clear?

jbuck@epimass.UUCP (06/18/87)

In article <8286@ut-sally.UUCP> atc@ut-sally.UUCP (Alvin T. Campbell III) writes:
>
>	I have a question for all you C wizards out there. I want to write 
>a function which returns a pointer to another function. I checked Kernighan
>& Ritchie and Harbison & Steele, but found no solution.

Script started on Wed Jun 17 21:08:03 1987
% cdecl
declare foo as function returning pointer to function returning int
int (*foo())()
% exit
script done on Wed Jun 17 21:08:49 1987

I typed the line beginning "declare", and cdecl shows me the
declaration.  I believe this program is in the comp.sources.unix
(formerly mod.sources) archives, available for anonymous FTP and
such.
-- 
- Joe Buck    jbuck@epimass.EPI.COM
	      {seismo,ucbvax,sun,decwrl,<smart-site>}!epimass.epi.com!jbuck
	      Old arpa mailers: jbuck%epimass.EPI.COM@seismo.css.gov

crowl@rochester.arpa (Lawrence Crowl) (06/18/87)

In article <7001@alice.UUCP> ark@alice.UUCP writes:
>The problem: how to declare a function that returns a function pointer:
>
>..., so we should say
>
>	extern int (*getfunc())();
>
>All clear?

This is not clear.  Let me propose a method for clearly coding complex
declarations.  I make use of the typedef facility.  So, for the example
above I will write:

     typedef  int                func_int() ;
     typedef  func_int           *ptr_func_int ;
     typedef  ptr_func_int       func_ptr_func_int() ;

     extern   func_ptr_func_int  getfunc ;

So what does this method buy me?  Well, it gives me a way to declare
other complex types without consulting K&R and a couple of C wizards
just to make sure the syntax is correct.  For instance, how about a
pointer to a function returning a pointer to an integer?

     typedef  int               *ptr_int ;
     typedef  ptr_int           func_ptr_int() ;
     typedef  func_ptr_int      *ptr_func_ptr_int ;

     extern   ptr_func_ptr_int  variable ;

What have I lost?  Well I have to type more.  However, the typedefs
need only be done once, so the true comparison is between:

     extern   int  (*getfunc())() ;
and
     extern   func_ptr_func_int  getfunc ;

I prefer the latter.
-- 
  Lawrence Crowl		716-275-5766	University of Rochester
			crowl@rochester.arpa	Computer Science Department
 ...!{allegra,decvax,seismo}!rochester!crowl	Rochester, New York,  14627

ka@hropus.UUCP (Kenneth Almquist) (06/18/87)

Given the code:
	int	(*func)();

	func = getmenu();
	(*func)();

Campbell wants to know how to declare getmenu.  Since we want getmenu
to return an object of the same type as func, we can simply take the
the declaration of func and replace "func" with what looks like a call
to getmenu.  This gives us:

	int	(*getmenu())();

To define getmenu, say:

	int (*getmenu())() {
		...
	}

Reading the declaration from "inside out", we see that getmenu is
a function returning a pointer to a function returning int.  Another
way to look at it is that (*getmenu())() is a C expression that
produces a result of type int.
				Kenneth Almquist

bright@dataio.Data-IO.COM (Walter Bright) (06/18/87)

In article <8286@ut-sally.UUCP> atc@ut-sally.UUCP (Alvin T. Campbell III) writes:
<	I have a question for all you C wizards out there. I want to write 
<a function which returns a pointer to another function. I checked Kernighan
<& Ritchie and Harbison & Steele, but found no solution.
<
<main()
<{	int	(*func)();
<
<	func = getmenu();
<	(*func)();
<}
<	So how do I declare getmenu() ?

int (*getmenu())();

The trick to doing declarations like these is to notice that the syntax
for the declaration of a variable is identical to the syntax for the use
of that variable. For example, to call a function:
	func();
To call a function using a pointer to a function, replace func with
*pfunc (parentheses are req'd because the trailing () binds more tightly):
	(*pfunc)();
To call a function using a pointer to a function that is returned by
another function getmenu, replace pfunc with getmenu():
	(*getmenu())();
and there is the declaration!

grk@sfsup.UUCP (G.R.Kuntz) (06/18/87)

In article <7001@alice.UUCP>, ark@alice.UUCP writes:
	:
	:
> 	extern int (*getfunc())();

In the original article, the call looked like

	(*func)();

and the return value was not used, so it would probably better to declare
getfunc as

	extern void (*getfunc())();

and define func as

	void (*func)();


			Cheers, Ralph
-- 
	G. Ralph Kuntz N2HBN	UUCP: {ihnp4,allegra}!attunix!grk
				ARPA: rutgers.rutgers.edu!pisc2b!grk
				PACKET: N2HBN @ NN2Z

gwyn@brl-smoke.ARPA (Doug Gwyn ) (06/19/87)

In article <8286@ut-sally.UUCP> atc@ut-sally.UUCP (Alvin T. Campbell III) writes:
>	int	(*func)();
>		func = getmenu();
>	So how do I declare getmenu() ?

As usual with C type declarations, all you need to do is declare the symbol
in the proper context; since getmenu() has type equivalent to func, simply
plug getmenu() in place of func in the declaration used for func:

	int	(*getmenu())();

This is similar to the C library signal() function (which has void basic
type instead of int).  Since your example didn't use the int supposedly
returned by (*func)(), perhaps you too should be using void not int.

gwyn@brl-smoke.UUCP (06/19/87)

In article <364@sol.ARPA> crowl@rochester.UUCP (Lawrence Crowl) writes:
>     extern   func_ptr_func_int  getfunc ;

The problem with this is that anyone reading your code would have to
untangle the several levels of typedef in order to determine the meaning
of this declaration, whereas with
	extern int (*getfunc())();
the meaning of the declaration is patent.  This is not a particularly
complicated construct; anyone who has to read C code should learn how
type specification works in C, after which this is easy to understand.

stevesu@copper.UUCP (06/19/87)

In article <8286@ut-sally.UUCP>, atc@ut-sally.UUCP (Alvin T. Campbell III) writes:
> 	I have a question for all you C wizards out there. I want to write 
> a function which returns a pointer to another function.

Ahh, this brings back fond memories of the first article I ever
posted to the net, which asked a related question (couched for
some odd reason in King James English).

The best way to declare a function returning a pointer to a
function returning an int is to use a typedef:

	typedef int (*PFI)();

	PFI function();

This has several advantages:

	it's much easier to understand,

	it makes it much easier to figure out which set of
	parentheses the function's arguments go in (this was my
	problem three years ago), and

	if you like to keep the name of the function at the left
	margin, you don't end up with unbalanced parentheses on
	the previous line.

Compare

	PFI
	getroutine(name, table)
	{...}

with

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

which pcc won't even compile, because the arguments actually
belong in the other set of parentheses.

                                           Steve Summit
                                           stevesu@copper.tek.com

hasch@gypsy.UUCP (06/19/87)

My solution in this case would be a typedef construct.
You define
	typedef int	(*FP)();
Now FP declares a type, which is a pointer to a function that returns an int.

Next declare
	FP	getfunc(), func;

I think the rest of the code can remain unchanged.

Harald Schaefer
Siemens RTL
... psuvax1!princeton!siemens!gypsy!hasch

drw@cullvax.UUCP (Dale Worley) (06/19/87)

atc@ut-sally.UUCP (Alvin T. Campbell III) writes:
> 	I have a question for all you C wizards out there. I want to write 
> a function which returns a pointer to another function. I checked Kernighan
> & Ritchie and Harbison & Steele, but found no solution.

int (*(f ())) ();

reading inside out:
	f is
	a function which returns
	a pointer to
	a function which returns
	int

Though this may not be discussed explicitly in K&R or H&S, it is
implied by the grammar and semantics discussed by both of them.

Dale
-- 
Dale Worley	Cullinet Software		ARPA: cullvax!drw@eddie.mit.edu
UUCP: ...!seismo!harvard!mit-eddie!cullvax!drw
If you light a match, how much mass does it convert into energy?

johnston@uiucdcsb.cs.uiuc.edu (06/19/87)

Try this:

	extern int (*getmenu())();

Explanation:

	int   X   ();		- X is a function returning int.
	int (*X  )();		- X is a pointer to a function returning int.
	int (*X())();		- X is a function returning a pointer
				  to a function returning int.

Alternative preferred by me:

	typedef int (*FUNC)();	/* FUNC - pointer to a function returning int */

	FUNC func;
	extern FUNC getmenu();

- Gary Johnston

Department of Computer Science
University of Illinois at Urbana-Champaign
1304 West Springfield Avenue
Urbana, IL 61801

Phone: (217) 333-2518

USENET:	{pur-ee,convex,ihnp4}!uiucdcs!johnston
ARPA:	johnston@b.cs.uiuc.edu
CSNET:	johnston%uiuc@csnet-relay