[net.lang.c] Array of pointers to functions

phil@osiris.UUCP (Philip Kos) (04/20/85)

An interesting question came up at work today.

A programmer here was wondering how you would declare an
array of pointers to functions returning pointers to
integers.  I've been able to generate code producing a
single pointer to a function returning a pointer to an
integer, as

	int *(*fp_ret_ip)();

but I've been unable to get the C compiler to accept an
array version of this.

Can this be done?  I've tried every combination of paren-
theses I could think of, but every time the comiler barfed
on it.

For the record, I'm using a Pyramid 90x running 4.2BSD/
SysV UNIX.


				Phil Kos
				The Johns Hopkins Hospital

gwyn@Brl-Vld.ARPA (VLD/VMB) (04/20/85)

> array of pointers to functions returning pointers to integers

	int *(*fp[10])();

works just fine on our C compilers; maybe Pyramid has a problem?

phil@osiris.UUCP (Philip Kos) (04/21/85)

Thanks to everyone who sent me answers.  I was apparently trying
to put the []'s in the wrong place.  Next time I'll remember
cdecl.

For the record, an array of pointers to functions returning type
foo is declared as:

    foo (*whatever[])();


					Phil

ark@alice.UUCP (Andrew Koenig) (04/21/85)

> A programmer here was wondering how you would declare an
> array of pointers to functions returning pointers to
> integers.  I've been able to generate code producing a
> single pointer to a function returning a pointer to an
> integer, as

> 	int *(*fp_ret_ip)();

> but I've been unable to get the C compiler to accept an
> array version of this.

Declare 'em like you use 'em:

	int *(*fp_ret_ip[10])();

This works just fine on my compiler; if it doesn't on yours,
maybe your compiler is broken.

brooks@lll-crg.ARPA (Eugene D. Brooks III) (04/22/85)

Declaring arrays of pointers to functions returning pointers to what ever
is always a pain to get straight.  The slickest solution (other than having
godlike mental powers) is documented in "C Notes" by Zahn.  You use a set of
typedefs to get the job done a step at a time.

/* First the type that the function returns. */

typedef int *PI;	/* PI is a pointer to an int. */

/* Now the function type. */

typedef PI FPI();	/* FPI is a function returning a pointer to an int. */

/* Now pointer to the above function. */

typedef FPI *PFPI;	/* PFPI is a pointer to a function returning a pointer to an int. */

Now an array of these pointers is as for any array.

PFPI array[10];		/* An array of function pointers of size 10. */

By building up these rather complicated declarations using typedefs the logic
of what you are declaring and how to use it is it bit easier to understand.

See "C Notes" by Zahn for a longer explanation of the above and the corrections
to any possible errors in the preceeding description.

jordan@greipa.UUCP (Jordan K. Hubbard) (04/23/85)

Ditto, I tried int *(fp_ret_ip[])() on my pyramid and it liked
it fine. I was too lazy to test it with an aggregate initialization
tho, So I can't in all honesty say that's the best way. Only thing I
can say is that there seems to be a definate difference in the
handling of * and [].. Some v7 compilers I've seen could give a hoot,
it's all the same to them. Others will consider the difference significant.

For instance:

On the last v7 compiler I used, these two statements were equally valid:

static char *foo = {
	"this",
	"that",
	"and the",
	"other thing"
};

static char foo[] = {
	"etc..",
	"and so",
	" forth"
};

However, a sysIII compiler on a 68K box would only grok the [] decl.
I guess a semantic difference would be that in the latter case you
were creating a temporarily unbounded array suitable for such an
initialization, whereas you were only allocating space for a pointer
before. But, as I say, it's semantic because you could also look at
the fact that the static array of pointers is going to be in some
compiler-reserved global area anyway & you are merely assigning the
address (I hesitated to say 'global section', shades of VMS!)..

This has been a puzzling question in the past & I have yet to run
into it on 4.2 because I haven't done much of that type of coding
on the pyramid yet.. I would welcome any flames/feedback or warnings
on the subject. Mail is probably best, I'll summarize if necessary.
(But HEY, if you want to start another discussion).
-- 
				Jordan K. Hubbard
				@ Genstar Rental Electronics.
				Palo Alto, CA.
				{sun, decwrl, dual}!twg!greipa!jordan

I'm your private hacker, hacking for money, any old keyboard will do..

					- Tina Turing

brahms@spp5.UUCP (Bradley S. Brahms) (03/04/86)

[}{]

Is it just the implementation of c on the AT&T 7300 or is it normal for c
not to allow arrays of function pointers?  I couldn't find any reference
to using arrays of function pointers in K&R but it seemed rather straight
forward.  To get around the problem I ended up defining a structure with a
pointer to a function as its only element then making an array of that
structure.  Either way, it seems that the end result is the same.

			-- Brad Brahms
			   usenet: {decvax,ucbvax,ihnp4}!trwrb!trwspp!brahms
			   arpa:   Brahms@usc-eclc

friesen@psivax.UUCP (Stanley Friesen) (03/05/86)

In article <111@spp5.UUCP> brahms@spp5.UUCP (Bradley S. Brahms) writes:
>
>Is it just the implementation of c on the AT&T 7300 or is it normal for c
>not to allow arrays of function pointers?  I couldn't find any reference
>to using arrays of function pointers in K&R but it seemed rather straight
>forward.

	It is "just" the "implementation" of on the ATT 7300. In fact
it is a *bug* in the ATT 7300 compiler. In 'C' ypu are allowed to do
anything that is not explicitly forbidden. You may make arrays of
*any* type except arrays of functions. Any compiler that forbids
arrays of function pointers is *broken*. In fact this is the only one
I have ever heard of that has this "restriction". You should call the
vendor (?AT&T) and complain about this bug.
-- 

				Sarima (Stanley Friesen)

UUCP: {ttidca|ihnp4|sdcrdcf|quad1|nrcvax|bellcore|logico}!psivax!friesen
ARPA: ttidca!psivax!friesen@rand-unix.arpa

woody%Juliet.Caltech.Edu@cit-hamlet.ARPA (04/06/86)

I'm confused.  How do you specify an array of pointers to functions?  Do
you do it:

           int (*foo[])();

or do you do it:

           int ((*foo)())[];


The reason why I'm asking is that I need to create a static array of 
pointers to functions, and have it portable; my slightly used brain
cells tell me the second one makes sense  (after all, a pointer to a
function is 'int (*foo)();'; thus, an array of them should be done by
adding the '[]' at the end).  Yet, the C compiler I'm using wants it
the first way and the logic excapes me as to why.

Please send all responces directly to me.  And please don't flame me;
I'm really confused about this point which is (as far as I can tell) not
in K&R.
         - William Woody
      NET  Woody%Romeo@Hamlet.Caltech.Edu
   USNAIL  1-54 Lloyd, Caltech / Pasadena, CA 91126

dan@BBN-PROPHET.ARPA (04/07/86)

Re array of pointers to functions: the way I think of it is that C
declarations must be read "from the inside out".  Start with the
identifier itself, and work your way out from the tightest-binding
declaration operator to the loosest.  The first declaration operator you
hit gives you the fundamental type of the object.  So, given a declaration
containing

	... (*x) ...

No matter what is surrounding the "(*x)", x is a pointer.  Always.
Never an array, function, etc., though what it points to may involve
these.  On the other hand, given

	... (x[5]) ...

X is definitely an array of 5 (somethings).  Maybe pointers, ints, etc.
So, to construct an array of pointers, you say

	(x[])

to get the array, and add the '*' next:

	(*(x[]))

Now it's an array of pointers.  What do they point to?  Functions:

	( (*(x[])) () )

Now all you need to do is specify what the functions return:

     int ( (*(x[])) () )

And you're done.  However, you've left behind a pretty confusing
declaration.  C typedefs are the perfect way to make things like this easy
to understand:

    typedef int FUNC();
    typedef FUNC * FUNC_PTR;
    FUNC_PTR x[];

Now it's quite clear that x is an array of function pointers.  I usually
use some variation on this when I have to construct such arrays; it's a
lot clearer, even to people like me who have been using C for years.
Hope this helps.

	Dan Franklin

woody%Juliet.Caltech.Edu@cit-hamlet.ARPA (William E. Woody) (04/08/86)

  Yesterday I asked which was right:  "int (*foo[SIZE])()" or
"int ((*foo)())[];" today I got several answers from a few folks out in
net-land.  Thank you everyone for helping me out in this small point of
confusion.  Though I have been using C for a couple of years, up until
today the section of K&R on declaring variables mystified me; now I know
a lot better.

  The solution I got was to look at declarations from the inside out; thus

     int foo                       - An integer
     int *foo                      - A pointer to an integer
     int (*foo)[]                  - An array of pointers to integers
     int ((*foo)[])()              - An array of pointers to functions
                                     returning integers.

  The whole thing reads from inside out, just as english reads from right to
left.

  Thank you very very much for your time and trouble on this one, net landers!
         - William Woody
      NET  Woody%Romeo@Hamlet.Caltech.Edu
   USNAIL  1-54 Lloyd, Caltech / Pasadena, CA 91126

tombre@crin.UUCP (Karl Tombre) (04/08/86)

In article <2398@brl-smoke.ARPA> woody%Juliet.Caltech.Edu@cit-hamlet.ARPA writes:
>I'm confused.  How do you specify an array of pointers to functions?  Do
>you do it:
>
>           int (*foo[])();
>
>or do you do it:
>
>           int ((*foo)())[];

Your compiler is right of course in taking the first as valid. A you say,
this may not be given in K&R, but I found some equivalence rules in another
book : "Advanced C: food for the educated palate", by N. Gehani, Computer
Science Press (ISBN 0-88175-078-6). You can find out this way:

     foo             : array of pointers to functions returning int
=>   foo[]           : pointer to function returning int
=>   *foo[]          : function returning int
=>   (*foo[])()      : int

and thus you have the right syntax.

I posted this rather than replying as you are not on UUCP and I have already
experienced that mail sent through complex channels does not reach its
destination easily.

Best regards,
-- 
--- Karl Tombre @ CRIN (Centre de Recherche en Informatique de Nancy)
UUCP:    ...!vmucnam!crin!tombre  or    ...!inria!crin!tombre
COSAC:   crin/tombre
POST:    Karl Tombre, CRIN, B.P. 239, 54506 VANDOEUVRE CEDEX, France

Les plus desesperes sont les chants les plus beaux,
Et j'en sais d'immortels qui sont de purs sanglots.

       Alfred de Musset.

throopw@dg_rtp.UUCP (Wayne Throop) (04/10/86)

> I'm confused.  [Is] an array of pointers to functions [declared like this]?
>            int (*foo[])();
> [or like this?]
>            int ((*foo)())[];
> [...]
> I'm really confused about this point which is (as far as I can tell) not
> in K&R.
>     William Woody    Woody%Romeo@Hamlet.Caltech.Edu

Actually, it *is* in K&R, though in an unexpected place.  Page 90.
(Ahem.)

    [...] the syntax of the declaration for a variable mimics the syntax
    of expressions in which the variable might appear.

Thus, your second example is indirected, then invoked, then subscripted,
so it is a pointer to a function returning an array (that is, really a
function returning a pointer, though this point is obscure).  Your first
example is subscripted, then indirected, then invoked, so it is an array
of pointers to functions.  I always fully parenthesize declarations, so
that I'd prefer the first to be "int (*(foo[]))();", just so that the
order is less likely to be mistaken.

In general, to construct any compound type involving invocation
(function returning), indirection (pointer to), or subscription (array
of), start from the name, and build outward.  For example, let's
construct a declaration of an array of pointer to int.

                foo[]                   array of
                *(foo[])                pointer to
        int     *(foo[]);               int

Or construct a declaration of a function returning pointer to char

                foo()                   function returning
                *(foo())                pointer to
        char    *(foo());               char

The construction method is simple.  As you read through the description
of what you want, just take the previous stuff, parenthesize (to avoid
ambiguity), add the new operation to the outside, and top it off with
the primitive type.  Thus, the example of array of pointer to function
returning int becomes

                foo[]                   array of
                *(foo[])                pointer to
                (*(foo[]))()            function returning
        int     (*(foo[]))();           int

Note that reading one of these declarations aloud is easy as well.  Just
start from the name, and read the operators that are applied in turn
aloud until you get to the primitive type.  "*" is read as "pointer
to", "[]" as "array of", and "()" as "function returning", and grouping
parenthesis are silent.  For example,

    in this declaration:             int   *((*(foo[]))());
    operations are in this order:          4  2    1   3

so it is an array of pointer to function returning pointer to int.


Now, this is one of those recurring topics.  I'll agree that C's type
declaration syntax is peculiar, and hard to follow at first glance.  But
I do wonder.... just why does anybody think that "int ((*foo)())[];" is
an array of pointer to function?  The obscurity of the explanatory K&R
passage aside, just what do you folks *do* when you try to construct a
declaration in C?  This question is *not* rhetorical, nor intended as an
insult.... I'd really like to know how folks go about constructing
variable and type declarations in C.  Please mail me your methods...
I'll post a summary if the response warrants it.
-- 
Wayne Throop at Data General, RTP, NC
<the-known-world>!mcnc!rti-sel!dg_rtp!throopw

throopw@dg_rtp.UUCP (Wayne Throop) (04/11/86)

AAAAUUUUGGGGHHHH!!!!

> Yesterday I asked which was right:
>     "int (*foo[SIZE])()" or "int ((*foo)())[];"
> The solution I got was to look at declarations from the inside out; thus
>      int foo                       - An integer
>      int *foo                      - A pointer to an integer
>      int (*foo)[]                  - An array of pointers to integers
>      int ((*foo)[])()              - An array of pointers to functions
>                                      returning integers.

Puh*LEEZE* try to be a little more careful, folks.  It is probable that
the error in the above is a typo, but typo or not, it spreads
misinformation.  The general principle of declaring from the inside out
is correct as stated above, but the last two examples are *INCORRECT*.

In particular, (*foo)[] is a pointer to an array, not an array of
pointers.  Read it from the inside out folks... pointer operation first,
then array, hence "pointer to array".  Similarly for the last example.
It is a pointer to an array of functions returning int, which isn't even
legal in C.

If the last example had been typechecked before posting, it would have
been obvious that it was bogus... lint barfs all over it, saying:

        array of functions is illegal

In addition, a local typechecker gives a somewhat more verbose
admonition, like so:

        arrays cannot contain this type
              (:FUNCTION_RETURNING (:INT))

As I've said before, puh*LEEZE* be more careful, and (where possible)
*TYPECHECK* *POSTED* *EXAMPLES* (with lint at least, and maybe more if
you've got more).
-- 
Wayne Throop at Data General, RTP, NC
<the-known-world>!mcnc!rti-sel!dg_rtp!throopw

mouse@mcgill-vision.UUCP (der Mouse) (04/12/86)

Well, I  tried to mail this, but the percent sign  got @ified  somewhere
along  the  way,  then  some later  mailer  bounced it because of  that.
Besides, this may help someone else,  or at  least so I  rationalize  to
myself.

> I'm confused.  How do you specify an array of pointers to functions?  Do
> you do it:
>            int (*foo[])();
This is right.
> or do you do it:
>            int ((*foo)())[];
This specifies  a  pointer to a function returning an  array of ints, if
read  literally.    Since  functions  cannot return  arrays (as  current
compilers stand), this is nonsense, but that's what it says.

> (after all, a pointer to a function is 'int (*foo)();'; thus, an array of
> them should be done by adding the '[]' at the end).
> Yet, the C compiler I'm using wants it the first way and the logic excapes
> me as to why.

     Here is  a  technique which  I have found  helps  with  complicated
declarations; it  consists of  building  the declaration one  piece at a
time, parenthesizing fully as you go.  In this case:

Foo should be...
	         foo
...an array of...
	        (foo)[]
...pointers to...
	      *((foo)[])
...functions returning...
	     (*((foo)[]))()
...int
	int ((*((foo)[]))())

This is a valid declaration and will work.   Some of the parentheses can
be stripped out, however:

	int ((*((foo)[]))())
() binds tighter than the `int', get rid of one pair
	    x              x
	int  (*((foo)[]))()
() binds tighter than *, keep the next pair
	     x          x
	int  (*((foo)[]))()
[] binds tighter than *, get rid of the next pair
	       x       x
	int  (* (foo)[] )()
The innermost pair is totally unnecessary
	        x   x
	int  (*  foo [] )()
and we have the original declaration.  If  you are not sure which of two
things binds tighter, well, it can never hurt  to  leave the parentheses
in, so when in doubt.....

     I have  yet to  see a type which will not  yield to this technique.
Of course, some types do not exist, such as arrays of functions,
	int foo[]();
or functions returning arrays,
	int foo()[N];
or functions returning functions,
	int foo()();
though functions returning pointers to functions are OK.
	int (*foo())();
The declarations can be written, however.

     You were almost right in talking about throwing  [] on  the end  of
the one to get the other; what you need to do is throw the [] on the end
of  the variable (possibly  with parentheses), not the end of  the whole
declaration.
-- 
					der Mouse

USA: {ihnp4,decvax,akgua,utzoo,etc}!utcsri!mcgill-vision!mouse
     philabs!micomvax!musocs!mcgill-vision!mouse
Europe: mcvax!decvax!utcsri!mcgill-vision!mouse
        mcvax!seismo!cmcl2!philabs!micomvax!musocs!mcgill-vision!mouse
ARPAnet: utcsri!mcgill-vision!mouse@uw-beaver.arpa

Wizard:  One who can find and fix bugs in an emergency
	(such as during a site visit by funding agencies).

cjl@iuvax.UUCP (04/14/86)

> I'm confused.  How do you specify an array of pointers to functions?  Do
> you do it:
>           int (*foo[])();
> or do you do it:
>           int ((*foo)())[];

  If C enforces postfix notations for all its declarations, the world will 
be more peaceful. Two of its declarators use postfix notation ( [] and () ),
while pointer uses prefix notation ( * ). Confusion about declarator precedence
will disappear IF we CHANGE the syntax of pointer declarator to a postfix
notation. So when we speak "an array of pointers to functions", we
can write down immediately as "int foo [] * ()". To face the reality
in the C world, we translate the above back into " (* (foo [])) () ".
(Parentheses are used here to avoid the precedence problem.)
Remembering the rule that postfix declarators has higher priority than
prefix declarators, we can save some of the parentheses as
" (* foo []) () ".


C.J.Lo
UUCP : ...!iuvax!cjl
ARPA : cjl@Indiana@CSNet-Relay

rjnoe@riccb.UUCP (Roger J. Noe) (04/15/86)

> 		just what do you folks *do* when you try to construct a
> declaration in C?  This question is *not* rhetorical, nor intended as an
> insult.... I'd really like to know how folks go about constructing
> variable and type declarations in C.  Please mail me your methods...
> I'll post a summary if the response warrants it.
> -- 
> Wayne Throop at Data General, RTP, NC

Tough luck, Wayne, I feel like posting this.  See article <662@riccb.UUCP>
in net.sources.  It's a shell program to convert words to C declarations or
casts, somewhat similar to the CDECL seen on the net before but somewhat more
portable and easier to modify.  Hope it's some use to somebody.  I welcome
comments and suggestions regarding it.
--
"Listen, in order to maintain airspeed velocity a swallow needs to beat
 its wings forty-three times every second.  Right?"
	Roger Noe			ihnp4!riccb!rjnoe

herndon@umn-cs (04/25/86)

   If you really want to change the syntax, you should look at
Ravi Sethi's article a few years ago on improving the type
declarations of the C language.  He made a number of relevant
suggestions, all of which made good sense to me.
  Unfortunately, changing this syntax would break so many
programs as to be infeasible.  Does anyone know where
this article is?  I seem to recall that it was either in
Software Practice & Experience, SIGPLAN Notices, or else it
was in a conference proceedings somewhere.

					Robert Herndon

Unknown@brl-smok (04/25/86)

This message is empty.

davidsen@steinmetz.UUCP (Davidsen) (05/02/86)

Another way to build unusual declarations is by repeated typedefs. The
previous posting gave as an example "array of pointers to function
returning integer", which is "int (*foo[])()".

To build this up:
typedef int fri();		/* function returning int */
typedef fri *pfri;		/* prointer to function ret. int */
typedef pfri apfri[20];		/* array (size 20) of ... */

Then:
apfri foo; /* declares the array */
-- 
	-bill davidsen

	seismo!rochester!steinmetz!--\
       /                               \
ihnp4!              unirot ------------->---> crdos1!davidsen
       \                               /
        chinet! ---------------------/        (davidsen@ge-crd.ARPA)

"Stupidity, like virtue, is its own reward"