Syntax of function prototypes...

Chris Torek chris at mimsy.UUCP
Sat Aug 20 11:57:08 AEST 1988


In article <4165 at adobe.COM> burgett at steel.COM (Michael Burgett) writes
[in re `int foo();' as a `prototype' declaration]:

>By function prototyping you have to declare the type and number (or
>indicate that there is a variable number) of parameters ....

Right: the key is that while `int foo();' *is* a function declaration,
it is *not* a /prototype/ declaration.

>If this [form of declaration] is used with ANSI I believe the 
>compiler will look at the first time you use a function to determine the 
>arguments...

Any compiler that does this implements none of the draft proposed
American National Standards for C.  The declaration

	int foo();

is morally equivalent to the prototype declaration

	int foo(...);

although the latter is in fact illegal.

Aside: I think this illegality is a mistake, though a minor one.
Consider the `tovector' function, which counts the number of valid
pointers passed to it and constructs a vector holding this list, then
passes the vector as an argument to a function.  It is called as
`tovector([optional PTR arguments], (PTR)NULL)'.  Here it is in `old
C', slightly compressed vertically:

	typedef char *PTR;	/* generic pointer type */
	#define	NULL	0
	#include <varargs.h>
	char *malloc();

	PTR *tovector(va_alist) va_dcl {
		int veclen;
		PTR *v, *p;
		va_list ap;

		/* find the vector length, including the NULL */
		va_start(ap);
		veclen = 0;
		do veclen++; while (va_arg(ap, PTR) != NULL);
		va_end(ap);
		/* create the vector */
		v = (PTR *)malloc((unsigned)veclen * sizeof(PTR));
		if (v == NULL) return (NULL);
		va_start(ap);
		for (p = v; (*p++ = va_arg(ap, PTR)) != NULL;) /* void */;
		va_end(ap);
		return (v);
	}

This is reasonably straightforward.

Here it is again, this time in dpANS C:

	typedef void *PTR;	/* generic pointer type */
	#include <stddef.h>
	#include <stdarg.h>

	PTR *tovector(PTR firstarg, ...) {
		int veclen;
		PTR *v, *p;
		va_list ap;

		/* find the vector length, including the NULL */
		veclen = 1;
		if (firstarg != NULL) {
			va_start(ap, firstarg);
			do veclen++; while (va_arg(ap, PTR) != NULL);
			va_end(ap);
		}
		/* create the vector */
		v = (PTR *)malloc((unsigned)veclen * sizeof(PTR));
		if (v == NULL) return (NULL);
		p = v;
		*p++ = firstarg;
		if (firstarg != NULL) {
			va_start(ap, firstarg);
			while ((*p++ = va_arg(ap, PTR)) != NULL) /* void */;
			va_end(ap);
		}
		return (v);
	}

Notice that this time the code must be littered with special
tests for the first argument.

Certainly this is a rare case: most varargs appear after 1, 2, or
even more fixed arguments, and this problem does not arise.  But
it is not a nonexistent case, and the inelegance of disallowing
no fixed arguments is at least inconvenient.  (How is that for a
sentence full of negatives? :-) )
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list