[comp.sys.mac.programmer] Arrays of functions in THINK C

phil@mit-amt.MEDIA.MIT.EDU (Phil Sohn) (08/03/88)

typedef int (*GEN)();

int gen01();

GEN gensub[10]= {NULL, gen01}

gensub[1]();  <-  compiler produces an error here


	Anyone see what I am doing wrong?  I believe it
is a bug in THINK C  (including 3.0) because it works on
Vaxes, HPs, Suns, and in MPW.
	Does Anyone know a good way to do the samething
in THINK C?


				phil@ems.media.mit.edu

earleh@eleazar.dartmouth.edu (Earle R. Horton) (08/03/88)

In article <2884@mit-amt.MEDIA.MIT.EDU> phil@mit-amt.MEDIA.MIT.EDU (Phil Sohn) writes:
>typedef int (*GEN)();
>
>int gen01();
>
>GEN gensub[10]= {NULL, gen01}
>
>gensub[1]();  <-  compiler produces an error here
>
>
>	Anyone see what I am doing wrong?  I believe it
>is a bug in THINK C  (including 3.0) because it works on
>Vaxes, HPs, Suns, and in MPW.

Try

(* gensub[1])();

I don't think it's a bug in Think.  I think Think is handling the
situation properly.  In the first form, you are attempting to call a
pointer to a function.  In the second form, you are calling the
function referenced by the pointer.  The reason the first form works
on "Vaxes, HPs, Suns, and in MPW" is rather obvious:  "What else could
I possibly mean here?"  K&R doesn't say anything about it.  Anybody
care to eleaborate about what ANSI says?

Mr. Spock!  This disk is damaged!  Do you want to initialize it?

Earle R. Horton.  H.B. 8000, Dartmouth College, Hanover, NH 03755

nagel@ics.uci.edu (Mark Nagel) (08/03/88)

In article <9651@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle R. Horton) writes:
|In article <2884@mit-amt.MEDIA.MIT.EDU> phil@mit-amt.MEDIA.MIT.EDU (Phil Sohn) writes:
[ stuff about how gensub[x]() doesn't work in LSC ]
|
|Try
|
|(* gensub[1])();
|
|I don't think it's a bug in Think.  I think Think is handling the
|situation properly.  In the first form, you are attempting to call a
|pointer to a function.  In the second form, you are calling the
|function referenced by the pointer.  The reason the first form works
|on "Vaxes, HPs, Suns, and in MPW" is rather obvious:  "What else could
|I possibly mean here?"  K&R doesn't say anything about it.  Anybody
|care to eleaborate about what ANSI says?

I'm relatively sure that ANSI says that if fp is a function pointer then
both (*fp)() and fp() are equivalent.

--
Mark D. Nagel
Department of Information and Computer Science, UC Irvine
nagel@ics.uci.edu             (ARPA)             When they ship styrofoam...
{sdcsvax|ucbvax}!ucivax!nagel (UUCP)             ...what do they pack it in?

breck@aimt.UUCP (Robert Breckinridge Beatie) (08/03/88)

In article <9651@dartvax.Dartmouth.EDU>, earleh@eleazar.dartmouth.edu (Earle R. Horton) writes:
> In article <2884@mit-amt.MEDIA.MIT.EDU> phil@mit-amt.MEDIA.MIT.EDU (Phil Sohn) writes:
> >typedef int (*GEN)();
> >
> >int gen01();
> >
> >GEN gensub[10]= {NULL, gen01}
> >
> >gensub[1]();  <-  compiler produces an error here
> >
> 
> Try
> 
> (* gensub[1])();
> 
> ... K&R doesn't say anything about it.  Anybody
> care to eleaborate about what ANSI says?


Actually, K&R does say something about it.  On page 182  (section 7.1
of appendix A)  it says:

	A function call is a primary expression followed by parentheses
	containing a possibly empty, comma-separated list of expressions
	which constitute the actual arguments to the function.  The
	primary expression must be of type "function returning ...", and
	the result of the function call is of type "...".

At least I take this to mean that the primary expression shouldn't be
of type "pointer to function returning ...".  Funny, it's the unix
compilers that are broken in this case.  Of course my "analysis" may
be flawed.

Anyway, ANSI (October 1986 draft) proposal says in section 3.3.2.2:

	The expression that denotes the function called shall have type
	"pointer to function"*

	* Most often, this is the result of converting an identifier
	  that is a function designator.

So, the unix compilers conform to ANSI, but not K&R and LSC conforms to
K&R, but not ANSI.  Or so I think.

-- 
Breck Beatie	    				(415)856-8649
{uunet,ames!coherent}!aimt!breck
"Sloppy as hell Little Father.  You've embarassed me no end."

jimc@iscuva.ISCS.COM (Jim Cathey) (08/03/88)

In article <9651@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle R. Horton) writes:
>Try
>
>(* gensub[1])();
>
>I don't think it's a bug in Think.  I think Think is handling the
>situation properly.  In the first form, you are attempting to call a
>pointer to a function.  In the second form, you are calling the
>function referenced by the pointer.  The reason the first form works
>on "Vaxes, HPs, Suns, and in MPW" is rather obvious:  "What else could
>I possibly mean here?"  K&R doesn't say anything about it.  Anybody
>care to eleaborate about what ANSI says?

I've always hated this characteristic in compilers.  Ever since many 
programmers around here cut their teeth on the old Mark Williams C compiler
for the IBM PC.  That little gem generalized the "what else could I
possibly mean" principle to include converting structure passing operations
into structure reference operations since it couldn't do the former (that is,
it automatically supplied the '&' without even warning you).  Combine this
with the old "Of course ints and pointers are the same size, what else could
possibly make sense?" You can imagine what happened when all these people  
moved to writing programs on the Vax and 68000.

C's syntax is confusing enough without having it automagically convert
selected expressions into something else.  Dammit, so you can't have
arrays of functions _this_ year.  Don't forgive syntax mistakes/
shortcuts anyway!  (Yes, I know arrays of functions don't make much
sense, but so what?  What about on your custom neural net/parallel
super-femtocomputer?) 

+----------------+
! II      CCCCCC !  Jim Cathey
! II  SSSSCC     !  ISC Systems Corp.
! II      CC     !  TAF-C8;  Spokane, WA  99220
! IISSSS  CC     !  UUCP: uunet!iscuva!jimc
! II      CCCCCC !  (509) 927-5757
+----------------+
			Member:  Society of the Excruciatingly Correct.

rcb@rti.UUCP (Random) (08/04/88)

>>Try
>>
>>(* gensub[1])();
>>
>

As a matter of fact, try looking up the error message in the manual.
It even has an example that goes something like:

	int foo[10]();		/* illegal */

	int (*foo[10])();	/* legal */


-- 
					Randy Buckland (919)-541-7103
					Research Triangle Institute
					rcb@rti.rti.org [128.109.139.2]
					{decvax,ihnp4}!mcnc!rti!rcb

andrew@ems.Ems.MN.ORG (Andrew C. Esh) (08/08/88)

In article <2884@mit-amt.MEDIA.MIT.EDU> phil@mit-amt.MEDIA.MIT.EDU (Phil Sohn) writes:
>typedef int (*GEN)();
>
>int gen01();
>
>GEN gensub[10]= {NULL, gen01}
>
>gensub[1]();  <-  compiler produces an error here
>
>				phil@ems.media.mit.edu

	What?  Don't listen to the other guys, they're blatherheads.  First,
you need a SEMICOLON after the array declaration.  Second, what are you trying
to do with the typedef?  If all of the functions in the array will return an
int, like gen01 does, then what you need is:

int (*gensub[])() = {NULL, gen01};	/* semicolon, sir! */

	(*gensub[1])();			/* This will call gen01, guaranteed */

	Probably ought to change that NULL to a reference to a routine that
simply returns a zero, or some other error value.  If you do a "(*gensub[0])()",
you'll get smoke and sparks (you'll start executing whatever is at zero, so
your program will probably magically start over, if you're lucky).
	Notice also that I did not hardcode the size of the array.  Since you're
doing a static initialization right there, you may as well let the compiler
count 'em up for you.  It will woof cookies when you add the eleventh entry,
otherwise.
	As for the rest of you, flame away.  I'm fireproof on this one.
I have the source (which has worked for 2 1/2 years now) right in front
of my beady little eyes. :-)
					- Andrew

"If it ain't fixed, don't broke it!"
-- 
Andrew C. Esh        DOMAIN: andrew@ems.MN.ORG     APPLELINK: D0492
EMS/McGraw-Hill      UUCP: ihnp4!meccts!ems!andrew      AT&T: (612) 829-8200

ed@mtxinu.UUCP (Ed Gould) (08/09/88)

>Actually, K&R does say something about it.  On page 182  (section 7.1
>of appendix A)  it says:

>	A function call is a primary expression followed by parentheses
>	containing a possibly empty, comma-separated list of expressions
>	which constitute the actual arguments to the function.  The
>	primary expression must be of type "function returning ...", and
>	the result of the function call is of type "...".

>At least I take this to mean that the primary expression shouldn't be
>of type "pointer to function returning ...".  Funny, it's the unix
>compilers that are broken in this case.  Of course my "analysis" may
>be flawed.

Your analysis is slightly flawed.  "function returning ..." can
mean, for example, function returning pointer to ...  A primary
expression that is a function call is not a pointer; it is a
reference to a pointer.  Consider

	char	*f();
	char	*(*g)();

	main() {
		g = f;
		f();
		g();
		(*g)();
	}

The declarations are for "f", a function returning pointer to char, and
"g", a pointer to a function returning pointer to char.  There are
three function calls in this program.  The first, "f()", is the usual
sort of call:  "f" is the name of a function.  The second, "g()" is a
misleading form:  It looks like "g" is the name of a function, but
really it's an implicit dereference (this form may not be alliwed by
ANSI - I'm not sure).  The third is an explicit dereference of a
pointer to a function.

To get back to the original question about arrays of functions, they
are not allowed so far as I know.  Arrays of pointers to functions
are.  Consider:  What would be the definition of an array of functions,
anyway?  Would

	f[2]()
	{
		printf("this if f[0]\n");
	}
	{
		printf("this is f[1]]\n");
	}

be one?  This isn't legal syntax, nor is there any.  An array of
pointers to functions (all returning the same type - pointer to
char in this example) may be declared

	char	*(*h)[];

-- 
Ed Gould                    mt Xinu, 2560 Ninth St., Berkeley, CA  94710  USA
{ucbvax,uunet}!mtxinu!ed    +1 415 644 0146

"I'll fight them as a woman, not a lady.  I'll fight them as an engineer."