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