[comp.lang.c] Solution of array of pointers to functions problem

dooley@helios.toronto.edu (Kevin Dooley) (06/14/89)

In a very recent posting I asked why it was illegal to construct
an array of pointers to functions.  The answer is, of course, that
it is completely legal, but with a twist.  The answer was graciously
suplied by Steve Lamont (thanks again).  Here is the expurgated version
of what he said:

>  ...Assuming that you want to do something like
>
>	double	foo();
>	double	bar();
>	double	baz();
>	double	woof();
>	double	arf();
>
>	typedef double	(*function)();
>
>	function	functionList[] = { foo, bar, baz, woof, arf };
>
>you can then invoke your favorite function in the following manner:
>
>	someReturnValue = (*functionList[index])( your favorite args );

Steve points out that the typedef is critical, ie

	double	(*functionList[])() = { ... };

*DOES**NOT**WORK*.  This is the peculiarity that I was missing.  Now
everything works beautifully.  So the big question at this point is
why is the typedef necessary?  I thought that typedef was *NEVER* 
required.  Anybody know the answer?

PS.  I'd like to thank all of the people who supplied correct responses.
I mention Steve's only because it was so concise, correct and ... well,
first.  I do not thank any of the people who assumed that I was a complete
idiot (no names, you know who you are).  As you see, there was something
nontrivial involved and the subject is not covered in either K&R.

		Kevin Dooley

-- 
 Kevin Dooley         UUCP - {uunet,pyramid}!utai!helios.physics!dooley
 Physics Dept.        BITNET - dooley@utorphys
 U. of Toronto        INTERNET - dooley@helios.physics.utoronto.ca

spl@mcnc.org (Steve Lamont) (06/14/89)

In article <823@helios.toronto.edu> dooley@helios.physics.utoronto.ca (Kevin Dooley) writes:
<In a very recent posting I asked why it was illegal to construct
<an array of pointers to functions.  The answer is, of course, that
<it is completely legal, but with a twist.  The answer was graciously
<suplied by Steve Lamont (thanks again).  Here is the expurgated version
<of what he said:
<
<>  ...Assuming that you want to do something like
<>
<>	double	foo();
<>	double	bar();
<>	double	baz();
<>	double	woof();
<>	double	arf();
<>
<>	typedef double	(*function)();
<>
<>	function	functionList[] = { foo, bar, baz, woof, arf };
<>
<>you can then invoke your favorite function in the following manner:
<>
<>	someReturnValue = (*functionList[index])( your favorite args );
<
<Steve points out that the typedef is critical, ie
<
<	double	(*functionList[])() = { ... };
<
<*DOES**NOT**WORK*.  This is the peculiarity that I was missing.  Now
<everything works beautifully.  So the big question at this point is
<why is the typedef necessary?  I thought that typedef was *NEVER* 
<required.  Anybody know the answer?
<

Actually it *does* work (blush!) as a previous poster showed.  When I
cobbled up my example (yes, I *do* try to test my code before I reply to
someone's question), I guess that I managed to bungle something.  The
codelet (code fragment?)

	double	foo();
	double	bar();
	double	baz();
	double	woof();
	double	arf();

	double	(*functionList[])() = { foo, bar, baz, woof, arf };

indeed *is* valid.  I have not the slightest idea how I managed to cause
it *not* to work in the first place, but I can't seem to make it break
now. :-(

I just tested it again on two compilers, our BSD VAX and my perverted
SysV IRIS 4D and they're both quite happy with it.


-- 
							spl
Steve Lamont, sciViGuy			EMail:	spl@ncsc.org
North Carolina Supercomputing Center	Phone: (919) 248-1120
Box 12732/RTP, NC 27709

dooley@helios.toronto.edu (Kevin Dooley) (06/14/89)

In article <823@helios.toronto.edu> I write:
>In a very recent posting I asked why it was illegal to construct
>an array of pointers to functions.  The answer is, of course, that
>it is completely legal, but with a twist. ...
I went on to say:
>                  ... the typedef is critical, ie
>
>	double	(*functionList[])() = { ... };
>
>*DOES**NOT**WORK*.  ...

Well, as many people have noticed, I was full of beans.  Sorry, it
works today.... My syntax was shakey when I did this before, now I
see the error of my ways.  (Head dutifully hung in shame)
	Kevin Dooley

-- 
 Kevin Dooley         UUCP - {uunet,pyramid}!utai!helios.physics!dooley
 Physics Dept.        BITNET - dooley@utorphys
 U. of Toronto        INTERNET - dooley@helios.physics.utoronto.ca

davidsen@sungod.crd.ge.com (William Davidsen) (06/14/89)

In article <823@helios.toronto.edu> dooley@helios.physics.utoronto.ca (Kevin Dooley) writes:

| Steve points out that the typedef is critical, ie
| 
| 	double	(*functionList[])() = { ... };
| 
| *DOES**NOT**WORK*.  This is the peculiarity that I was missing.  Now
| everything works beautifully.  So the big question at this point is
| why is the typedef necessary?  I thought that typedef was *NEVER* 
| required.  Anybody know the answer?

Today's answer is "broken compiler." The following program, using no
typedef, compiles and runs on SunOS3, Xenix 2.3.1, Stellar (SysV),
Ultrix (BSD) and Convex (BSD).
________________________________________________________________

#include <stdio.h>

int t1(), t2(), (*ptr[])() = { t1, t2 };

main() {
  int n = 1;

  (*ptr[n])();
}

t1() { printf("T1\n"); }
t2() { printf("T2\n"); }
________________________________________________________________

It also works with the declarations separate, such as:
	int t1();
	int t2();
	int (*ptr[])() = { t1, t2 };

There is no need for the typedef, and I belive your compiler is faulty
if it does not work. 'Scuse, I mean "*DOES**NOT**WORK*".
	bill davidsen		(davidsen@crdos1.crd.GE.COM)
  {uunet | philabs}!crdgw1!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

hankd@pur-ee.UUCP (Hank Dietz) (06/17/89)

In article <823@helios.toronto.edu> dooley@helios.physics.utoronto.ca (Kevin Dooley) writes:
[stuff about making an array of function pointers....]

Hmm.  I never thought about it before, but what does ANSI C do
type-conversion-wise with args to a function accessed via a function pointer
expression?  Unless I'm confused, unlike old C, ANSI C is supposed to make
things be the type you specify in the prototype...  but function pointers
wouldn't have prototypes (or would they?).

For example, suppose that p is a pointer to either a function f which
returns an int and takes a short arg or to function g which returns an int
and takes a long arg...  what is the type, short or long, when the value 5
is passed in code like (*p)(5)?

						-hankd@ee.ecn.purdue.edu

chris@mimsy.UUCP (Chris Torek) (06/19/89)

In article <11964@pur-ee.UUCP> hankd@pur-ee.UUCP (Hank Dietz) writes:
>... unlike old C, ANSI C is supposed to make things be the type you
>specify in the prototype...  but function pointers wouldn't have
>prototypes (or would they?).

They would.

>For example, suppose that p is a pointer to either a function f which
>returns an int and takes a short arg or to function g which returns an int
>and takes a long arg...

This type does not exist in pANS C.  p may be declared as one or the
other, but not both.  Either value may be stored in p, provided p is
properly cast before the call.

>what is the type, short or long, when the value 5
>is passed in code like (*p)(5)?

If p is written as

	int (*p)(short);
	int f(short);

	p = f;
	(*p)(5);

the argument `5' is converted to a `short' on the way to f().  If
we then add

	int g(long);

and try

	p = g;

we should get a compile-time error.  Changing this to

	p = (int (*)(short))g;

should make it compile; however, the call

	(*p)(5);

will then attempt to pass a short 5 to a routine expecting a long;
what happens is not predictable.  Perhaps the workstation catches
fire.%  To make it predictable (and, incidentally, work), we can
instead use

	(*(int (*)(long))p)(5);

which will convert the 5 to a long on the way to g().

Note that a declaration like

	int (*p)();

is, like

	int f();

deprecated.
-----
% This does seem rather unlikely.  Still, defensive programming suggests
  that one keep a bucket of water handy. :-)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris