function pointer help needed

Alan Amaral amamaral at elrond.UUCP
Tue Jan 13 04:03:32 AEST 1987


In article <1327 at loral.UUCP>, jlh at loral.UUCP (Jim Vaxkiller) writes:
> I'm having a little problem with tables of pointers to functions.
> What I want to do is have several functions returning type void,
> then put their addresses into a table and execute the function by
> indexing into the table.  Assembly language programmers out there
> will recognize this as a simple jump table.  Now if I have my functions
> return ints I'm fat, dumb, and happy.  It's when I try to use functions
> returning voids that the compiler burps.  I know about the void problem
> in the 4.2BSD compiler and have typedef'd voids to ints, but to no avail.
> The following code fragment illustrates my problem.
> 
> 
> void				/* 2 do nothing routines returning */
> err0()				/*    different data types */
> {}
> 
> int
> err1()
> {}
> 
> static (*ptr_tbl[])() = {	/* table of 2 function pointers */
> 	err0,			/* this is what the compiler hates */
> 	err1
> };
> 
> main()
> {
> 	(*ptr_tbl[0])();		/* invoke function */
> }
> 
> 
> Granted, I could have my functions all return ints, but I don't want
> to do that because they don't return anything and lint complains.
> My system is a vax 11/750 running 4.2BSD UN*X.  Any suggestions on
> how to make this work would be much appreciated.
> 
> 
> 					Jim
> 
> Jim Harkins 
> Loral Instrumentation, San Diego
> {ucbvax, ittvax!dcdwest, akgua, decvax, ihnp4}!sdcsvax!sdcc6!loral!jlh


Here is one way:

void				/* 2 do nothing routines returning */
err0()				/*    different data types */
{printf("testing 123\n");}

int
err1()
{}

void (*ptr_tbl[2])();		/* table of 2 function pointers */

void init()
{
    ptr_tbl[0] = err0;
}

main()
{
	init();
	(*ptr_tbl[0])();		/* invoke function */
}


Here is another way:

int				/* 2 do nothing routines returning */
err0()				/*    different data types */
{}

int
err1()
{}

static (*ptr_tbl[])() = {	/* table of 2 function pointers */
	err0,			/* this is what the compiler hates */
	err1
};

main()
{
	(void) (*ptr_tbl[0])();		/* invoke function */
}


Neither causes complaints from cc or lint (except for the unused err1 in
the first example that is).  I have found that this method is VERY nice
for doing lots of different things cleanly.  For example, I have a Ray
Tracing program that uses this sort of mechanism all over the place for
keeping methods straight for each object that I am rendering.  For
example:

	/* intersect ray with all known objects */
	for(i=0; i<n_objects; i++)
	    (* object_list[i].intersect) (i,ray);

causes the intersection algorithm for each object to be called, causing
each object to intersect itself with the supplied ray.  This wouldn't be
necessary normally except that each object type has a different
mechanism and routine for the intersection process.  It could also be
done by calling an intersection routine that had a case statement and
checked what type of object each object was and called the right
algorithm, but this is so much cleaner.  Also, to add a new object is
almost trivial after the object specific code is written.  The mechanism
is as follows: In the initialization routine an array entry is filled
with the address of a routine that reads the data for each specific object
type.  When an object type is encountered the jump table causes the
corresponding routine to be called.  In the object read routine the data
is read and the address's for all the other methods (intersection,
shadowing, and attributes i.e. color or texture) are filled into the
object structure.  When the object is to be intersected, shadowed, or
the attributes of the object at a particular point are requested, the
requesting routine indexes into the object_list array (as above) and
calles the correct routine with the correct parameters.

This has a very clear advantage over every other method I have ever
used in that to add a new object type, all I have to do is to add a new
line in the initialization routine to load the object read routine, and
the object read routine fills in the rest.  It's especially nice in that
I can supply only the code that needs to be changed (the init routine)
in source format, and the rest in object format, and the user can add
new objects just like a UNIX s/p can add a new device driver.
-- 
uucp:	 ...decvax!elrond!amamaral		I would rather be a
phone:	 (603) 885-8075				fool than a king...
us mail: Calcomp/Sanders DPD (PTP2-2D01)
	 Hudson NH 	03051-0908



More information about the Comp.lang.c mailing list