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