[comp.std.c] Question about function pointers & prototypes

rickc@agora.UUCP (Rick Coates) (08/26/89)

I was using my more-or-less ANSI C compiler (Microsoft C for the PC),
and ran across a question about function prototyping:

I am using an array of pointers to functions to access procedures.  My
compiler complains about lacking a function prototype.  Since the 
procedures take from none to four differing parameters, how do I declare it?
Just as if it has variable arguments?  I'd have to look up how one declares
no or more arguments...

How about returns? Can I have some void, and some return an int?

Sorry if is this is too elementary for this newsgroup... I was just wondering.



Rick Coates
...!tektronix!reed!percival!agora!rickc

tneff@bfmny0.UUCP (Tom Neff) (08/26/89)

In article <1611@agora.UUCP> rickc@agora.UUCP (Rick Coates) writes:
>I am using an array of pointers to functions to access procedures.  My
>compiler complains about lacking a function prototype.  Since the 
>procedures take from none to four differing parameters, how do I declare it?

If the list of function pointers is such that the Nth entry is always
a function of a certain declaration, while the N+1th is always a function
of a certain OTHER declaration, etc., then it is probably better to use
a structure here than an array.  The structure declaration will let you
provide explicit prototypes for the component function (pointers).  If
one or more entries in the list really do take a variable number of
parameters, then the standard pANS "varargs" can be used in their
declaration within the structure.

This is a standard solution for installable drivers and the like.
-- 
"We walked on the moon --	((	Tom Neff
	you be polite"		 )) 	tneff@bfmny0.UU.NET

chris@mimsy.UUCP (Chris Torek) (08/27/89)

In article <1611@agora.UUCP> rickc@agora.UUCP (Rick Coates) writes:
>I am using an array of pointers to functions to access procedures.  My
>compiler complains about lacking a function prototype.  Since the 
>procedures take from none to four differing parameters, how do I declare it?
>Just as if it has variable arguments?  I'd have to look up how one declares
>no or more arguments...

The proposed standard seems (meaning `you should check this yourself')
to require that all function pointers `fit' in some other function pointer
storage cell.  You must, however, cast these pointers back to their
proper type before calling the functions retained.

That being the case, you can do something like this:

	/*
	 * basic_fptr is a basic function-pointer type: it is a
	 * pointer to a function of no arguments that returns void.
	 */
	typedef void (*basic_fptr)(void);

	/* this is syntactic sugar to make the table look pretty */
	#define	C(x) (basic_fptr)(x)

	/* here are the functions that go in the table */
	int f1(int a, char *b);
	void f2(void);
	double f3(double x);
	/* more as desired */

	/* here is the table itself */
	struct ftable {
		char	*ft_name;	/* the name */
		basic_fptr ft_fn;	/* the pointer */
		char	*ft_type;	/* remembers type of fn & args */
	} ftable[] = {
		"f1",	C(f1),		"int(int,char*)",
	/* the C() cast is not necessary on f2, but this looks symmetric */
		"f2",	C(f2),		"void()",
		"f3",	C(f3),		"double(double)",
		/* more as desired */
		0, 0, 0 /* end */
	};

	... /* many lines later */ ...

		for (p = ftable; p->ft_name != NULL; p++)
			if (strcmp(name, p->ft_name) == 0)
				break;
		if (p->ft_name == NULL) {
			error("not found");
			return (-1);
		}
		if (strcmp(p->ft_type, "void()") == 0) {
			p->ft_fn();	/* basic type is already void(void) */
			return (0);
		}
		if (strcmp(p->ft_type, "int(int,char*)" == 0)
			return ((int(*)(int,char*))p->ft_fn)(intarg, cparg);
		if (strcmp(p->ft_type, "double(double)") == 0) {
			return ((double(*)(double))p->ft_fn)(dblarg) > 0.0;
		panic("what a strange function! (%s)", p->ft_type);
		/* NOTREACHED */

For efficiency, you might want to use `magic number' values in the
ft_type field (since you can then switch() on it).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@smoke.BRL.MIL (Doug Gwyn) (08/28/89)

In article <19278@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>The proposed standard seems (meaning `you should check this yourself')
>to require that all function pointers `fit' in some other function pointer
>storage cell.

I don't recall any constraints that would imply this.  Pointers to
functions are far less "flexible" than object pointers.

bill@twwells.com (T. William Wells) (08/29/89)

In article <10835@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
: In article <19278@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
: >The proposed standard seems (meaning `you should check this yourself')
: >to require that all function pointers `fit' in some other function pointer
: >storage cell.
:
: I don't recall any constraints that would imply this.  Pointers to
: functions are far less "flexible" than object pointers.

One can cast any function pointer to another and back again, and use
the result. I've buried my dpANS so I can't quote chapter and verse
but this was discussed a while ago here.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

dfp@cbnewsl.ATT.COM (david.f.prosser) (08/29/89)

In article <10835@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <19278@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>>The proposed standard seems (meaning `you should check this yourself')
>>to require that all function pointers `fit' in some other function pointer
>>storage cell.
>
>I don't recall any constraints that would imply this.  Pointers to
>functions are far less "flexible" than object pointers.

Section 3.3.4, page 47, lines 4-7:

	A pointer to a function of one type may be converted to a
	pointer to a function of another type and back again; the
	result shall compare equal to the original pointer.  If a
	converted pointer is used to call a function that has a type
	that is not compatible with the type of the called function,
	the behavior is undefined.

Thus all function pointers are mutually convertible.  They are, as
Doug noted, not convertible to or from object pointers in any
portable manner.

Dave Prosser	...not an official X3J11 answer...