libes@cme.nist.gov (Don Libes) (05/10/91)
All the STDC (-like) compilers I use support varargs. (To be explicit, this includes Borland, DEC, GNU, and Microsoft compilers.) All the non-STDC compilers I use (too many to name) support varargs. Naturally, the non-STDC compilers don't support stdarg. The obvious question is: why bother using stdarg? Is any vendor really going to omit varargs 5 or even 10 years from now? I seriously doubt it. (I'm betting one of my coworkers money on this.) I suppose that eventually one may have to explicitly use some flag when compiling (say "-varargs"), but don't you think the support will always be provided by the vendor somehow? (All the STDC compilers already provide a shitload of extensions.) Yes, programs that use varargs are not conforming, but we (and I'm speaking strictly for my coworkers here) are trying for maximal portability in unknown environments. Either there is a curious irony here or I don't understand why STDC invented stdarg. (Admittedly, some non-STDC compilers don't even support varargs.) Some of my coworkers use 1) only stdargs, 2) only varargs, or 3) both with ifdefs to select between them. Other possibilities are 4) a macro package to cover-up the choice, 5) avoid entirely, and 6) you don't know what I'm talking about and pass everything as if it were an int. (1) This makes sense to me if you are writing for and only for a STDC environment. Otherwise it just doesn't fly in the real world. (3) Ghastly to read and write. (4) Code doesn't look like STDC, and it raises the question of the original point of the invention of stdarg if it's never actually used directly. Unfortunately, there ain't no way to make the STDC macros work on top a varargs implementation. Even worse, how do you explain to a new C programmer that they shouldn't use what's in STDC? Obviously, I think people who subscribe to (3) or (4) are misguided. Don Libes libes@cme.nist.gov ...!uunet!cme-durer!libes
torek@elf.ee.lbl.gov (Chris Torek) (05/10/91)
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 <varargs.h> /* 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 <stdarg.h>) 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
dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (05/10/91)
In <2755@muffin.cme.nist.gov> libes@cme.nist.gov (Don Libes) writes: >All the STDC (-like) compilers I use support varargs. (To be >explicit, this includes Borland, DEC, GNU, and Microsoft compilers.) >All the non-STDC compilers I use (too many to name) support varargs. Some months ago I had the dubious honor of porting 110,000 lines of UNIX C code to run under the pretty-much-ANSI-conformant High-C compiler from Metaware. In this environment, varargs.h is a hard link to stdarg.h. So varargs.h is supported, but that doesn't mean that "varargs" is supported -- your variadic functions had better use the "..." syntax and the ANSI macros, though you can #include either varargs.h or stdarg.h, whichever you prefer... -- Rahul Dhesi <dhesi@cirrus.COM> UUCP: oliveb!cirrusl!dhesi
dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (05/10/91)
In <13041@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) defines this convenience macro: #if __STDC__ #define VASTART(ap, last) va_start(ap, last) #else #define VASTART(ap, last) va_start(ap) #endif I would like to know if there is anything in the ANSI C standard that guarantees that this will work. Using the Metaware High C compiler (which I mention in another posting), I found that it didn't. The High C compiler was doing some fancy token-pasting in its va_start macro, and that token pasting didn't work right if I defined my own macro that invoked va_start. It caused me three days of pain. -- Rahul Dhesi <dhesi@cirrus.COM> UUCP: oliveb!cirrusl!dhesi
meissner@osf.org (Michael Meissner) (05/10/91)
In article <2755@muffin.cme.nist.gov> libes@cme.nist.gov (Don Libes) writes: | The obvious question is: why bother using stdarg? Is any vendor | really going to omit varargs 5 or even 10 years from now? I seriously | doubt it. (I'm betting one of my coworkers money on this.) I suppose | that eventually one may have to explicitly use some flag when | compiling (say "-varargs"), but don't you think the support will | always be provided by the vendor somehow? (All the STDC compilers | already provide a shitload of extensions.) A couple of things: 1) There were two or three machines that could not support varargs in any fashion (I don't remember the particulars). 2) Then there was pyramid which had '{' in va_start, and '}' in va_end. 3) The MIPS based computers also have a subtle bug with varargs. In the MIPS calling sequence, if the first two arguments were floating point, they were passed in FP registers, rather than the GP registers. However, varargs only works on the GP register set, so that if you have a varargs function which takes a floating point value as the first argument, the wrong values are used. 4) On the 32x32 systems, arguments are typically passed on the stack. However, for building the kernel, the convention is that the first two arguments are passed in r0 and r1. This breaks varargs programs, so I recently modified GCC to always pass arguments to stdargs functions on the stack. -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142 Considering the flames and intolerance, shouldn't USENET be spelled ABUSENET?
gwyn@smoke.brl.mil (Doug Gwyn) (05/11/91)
In article <2755@muffin.cme.nist.gov> libes@cme.nist.gov (Don Libes) writes: >All the STDC (-like) compilers I use support varargs. Not all the standard-conforming compilers that *I* use! >Yes, programs that use varargs are not conforming, but we (and I'm >speaking strictly for my coworkers here) are trying for maximal >portability in unknown environments. Either there is a curious irony >here or I don't understand why STDC invented stdarg. X3J11 invented ,...) and <stdarg.h> because there was a need for them in some implementation environments, and the <varargs.h> va_start macro did not have a slot for the crucial "hook" on a known parameter that is needed by some reasonable implementations. For portability, you need to code for three environments: (a) <stdarg.h> exists; you can rely on this #if __STDC__. (b) <varargs.h> exists; you can almost rely on this #if unix. (c) neither header exists; you might be able to provide your own implementation of <varargs.h> for such an environment, or you could try pretending that there are more arguments than needed, which is a kludge that works in many cases.