stdarg.h mostly broken (not using prototype, tsk)
Danny Thomas
vthrc at brolga.cc.uq.oz.au
Fri Mar 29 08:19:15 AEST 1991
chrisa at beldar.ma30.bull.com (Chris Anderson) writes
>The following program prints "0" when compiled on a 4D20:
>
> #include <stdarg.h>
> main() { foo(1); }
>
> foo(x) {
> va_list ap;
> va_start(ap, x);
> printf("%d\n", va_arg(ap, int));
> }
>
>However, if the "x" argument name is changed to "va_alist", then
>it prints "1", which is clearly the right answer.
>
>Do I detect a slight bias towards varargs.h here? :-)
to which David B.Anderson (SGI) responds
>Note that the function definition is inconsistent with stdarg.h.
>(Where is the ... in the above?)
No mention of declaration
[on soapbox]
a loose programming style was one of the bad things K&R C allowed to
develop and one of my pet peeves is people moaning about C
(implementations) when they are not making use of type
declarations/including header files, they are simply not giving the
compiler enough information for it to locate many simple syntactical and
semantic programming errors. I remember the first time I used ftell() and
couldn't figure out what was going wrong; of course it was returning a
long which I was storing in an int. When that occurred to me, I realised
how silly I'd been not to include stdio.h but the problem persisted even
after doing that until I had a look at the header file and discovered that
ftell() wasn't one of the functions being declared (this was many years
ago).
Although I don't have immediate access to a SGI system, I bet the
problem would go away with the following
#include <stdarg.h>
>> #include <stdio.h>
>> void foo(int x, ...);
main(void) { foo(1); }
>> void foo(int x, ...) {
va_list ap;
va_start(ap, x);
printf("%d\n", va_arg(ap, int));
>> va_end(ap);
}
NB ANSI requires prototypes to be in scope for functions making use of
variable arguments, in this case both printf and foo. Failure to employ
va_end leads to "undefined" behaviour in ANSI terminology, ie it'll
probably work but it may not after a compiler update or on porting to
another system.
Also the future directions part of the ANSI document describes
non-prototype function declarations and definitions to be obsolescent
(3.9.4 & 3.9.5). Apart from giving compilers the capacity to detect
incorrect function calls (or at least inconsistent definition and usage),
prototypes also "give the programmer explicit control over the function
argument type conversions, so that often innapropriate and sometimes
inefficient default widening rules for arguments can be suppressed"
[rationale 3.5.4.3]. Prototypes also allow the compiler to generate more
efficient code; the rationale mentions the case of const pointer arguments
and the possibility of a more efficient calling sequence for functions
taking a fixed number of arguments (also see Harbison & Steele 3ed
240-247).
Danny Thomas,
More information about the Comp.sys.sgi
mailing list