Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!wuarchive!uunet!stanford.edu!agate!dog.ee.lbl.gov!elf.ee.lbl.gov!torek From: torek@elf.ee.lbl.gov (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Do you use stdarg, varargs or ya-args? Message-ID: <13041@dog.ee.lbl.gov> Date: 10 May 91 12:00:18 GMT References: <2755@muffin.cme.nist.gov> Reply-To: torek@elf.ee.lbl.gov (Chris Torek) Organization: Lawrence Berkeley Laboratory, Berkeley Lines: 133 X-Local-Date: Fri, 10 May 91 05:00:18 PDT In article <2755@muffin.cme.nist.gov> libes@cme.nist.gov (Don Libes) writes: >The obvious question is: why bother using stdarg? There is one minor efficiency reason, and, of course, the `standardness' argument. The efficiency reason comes about because varargs() officially works like this: #include /* foo takes three fixed arguments and the rest are variable */ /* VARARGS3 */ void foo(va_alist) /* example 1 */ va_dcl { va_list ap; XYZ *xp; int i; long l; va_start(ap); xp = va_arg(ap, XYZ *); i = va_arg(ap, int); l = va_arg(ap, long); /* code to deal with varargs goes here */ va_end(ap); } People (including myself) often write something like: /* VARARGS3 */ void foo(xp, i, l, va_alist) /* example 2 */ XYZ *xp; int i; long l; va_dcl { va_list ap; va_start(ap); /* code to deal with varargs goes here */ va_end(ap); } but this is not in fact correct. (I know of no systems on which it breaks, but that does not mean such do not exist.) Where I believe ANSI went wrong is in adding a second parameter to va_start. The `...' syntax is not as great a problem. If one takes the attitude (as I have done) that `if example 1 fails, get an ANSI C compiler or forget it', we can then write foo() as: #if __STDC__ void foo(XYZ *xp, int i, long l, ...) { #else void foo(xp, i, l, va_alist) XYZ *xp; int i; long l; va_dcl { #endif va_list ap; va_start(ap); /* code to deal with varargs goes here */ va_end(ap); } which cuts the work in half when compared with the (currently required under the exact same assumptions): /* example 3 */ #if __STDC__ void foo(XYZ *xp, int i, long l, ...) { #else /* VARARGS */ void foo(xp, i, l, va_alist) XYZ *xp; int i; long l; va_dcl { #endif va_list ap; #if __STDC__ va_start(ap, l); #else va_start(ap); #endif /* code to deal with varargs goes here */ va_end(ap); } In any case, the requirement that the name of the last fixed argument be repeated is a maintenance headache. The compiler already must understand the new `...' syntax; it is little, if any, more difficult to add at the same time one more special compiler-specific syntax or semantic (which is then hidden behind va_start in ) for computing the address of the first varying argument. Thus even though the `extra' argument to va_start can be hidden behind Yet Another Macro: #if __STDC__ #define VASTART(ap, last) va_start(ap, last) #else #define VASTART(ap, last) va_start(ap) #endif so that example 3 becomes: /* example 4 */ #if __STDC__ void foo(XYZ *xp, int i, long l, ...) { #else /* VARARGS */ void foo(xp, i, l, va_alist) XYZ *xp; int i; long l; va_dcl { #endif va_list ap; VASTART(ap, l); /* code to deal with varargs goes here */ va_end(ap); } , I still believe that this extra argument was a mistake. >... don't you think [old varargs style] support will always be provided >by the vendor somehow? (All the STDC compilers already provide a >shitload of extensions.) Always: no; for the next 20 years: yes. :-) (Incidentally, I have forgotten: is a shitload more or less than an oodle? I think the list goes: one, a couple, a few, some, a dozen, a baker's dozen, lots, oodles, a shitload, a metric shitload, ... [where is George Weinert when you need him? :-) ]) -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov