Path: utzoo!yunexus!geac!syntron!jtsv16!uunet!lll-winken!lll-tis!ames!haven!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Syntax of function prototypes... Message-ID: <13114@mimsy.UUCP> Date: 20 Aug 88 01:57:08 GMT Article-I.D.: mimsy.13114 References: <8808171403.AA05181@ucbvax.Berkeley.EDU> <6105@venera.isi.edu> <4165@adobe.COM> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 98 In article <4165@adobe.COM> burgett@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 #includechar *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 #include 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@mimsy.umd.edu Path: uunet!mimsy!chris