[comp.std.c] <stdarg.h>

scs@adam.pika.mit.edu (Steve Summit) (04/09/89)

The following fails to compile under Microsoft C version 5.1:

	#include <stdarg.h>

	warning(fmt)
	char *fmt;
	{
	va_list arg_ptr;
	va_start(arg_ptr, fmt);
	verror("warning", fmt, arg_ptr, 0);
	va_end(arg_ptr);
	}

because the va_end implementation sets arg_ptr to NULL, which
is nowhere defined.  This strikes me as a bug.  The synopsis
section of Microsoft's documentation for the va routines shows
<stdio.h> being #included (which would, of course, take care of
the problem), but I don't think I should have to.  What sayeth
the pANS?  I know it guarantees you can #include standard header
files multiple times (a desirable property), but does it ever say
you have to #include one before you can #include another?  (This
would not be desirable.)

                                            Steve Summit
                                            scs@adam.pika.mit.edu

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/09/89)

In article <10014@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
- In article <10447@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
- -	warning(fmt)
- -	char *fmt;
- So is your lack of ,... after fmt in the function header [a bug].

Oops, the whole header is wrong, since it uses an "old style" declaration.
<stdarg.h> is supposed to be used only with ,... prototype style functions.

mark@jhereg.Jhereg.MN.ORG (Mark H. Colburn) (04/10/89)

In article <10447@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>The following fails to compile under Microsoft C version 5.1:
>
>	#include <stdarg.h>
>
>	warning(fmt)
>	char *fmt;
>	{
>	va_list arg_ptr;
>	va_start(arg_ptr, fmt);
>	verror("warning", fmt, arg_ptr, 0);
>	va_end(arg_ptr);
>	}
>

If you are going to be strictly pANS your delclaration for 
warning should be:

	warning(char *fmt, ...)
	{
		...
	}

There is no way to express variable arguments given the old
style declaration syntax (at least not portably).

Also, the pANS says that anything which is going to be called
with variable arguments must have a function prototype in
effect at the time of it being called.  So somewhere before 
calling warning(), you wold need to declare...

Function prototypes are generally a good thing, however, they
are not very portable.  I do something like the following in 
my code:


	/* function prototypes */
	#ifdef __STDC__
	int	warning(char *, ...);
	#endif


	#ifdef __STDC__

	warning(char *fmt, ...)

	#else

	warning(fmt)
	char *fmt;

	#endif
	{
	}

It takes up a lot more space, but it allows the code to adapt
to the environment.  It is not all that hard to read once you
get used to it either...

>because the va_end implementation sets arg_ptr to NULL, which
>is nowhere defined.  This strikes me as a bug.  

Va_end should not cause a problem by setting arg_ptr to NULL.
I assume that you mean va_start()?  This may well be because
there is no prototype in scope and/or that there are no 
elipses in your function declaration.

>section of Microsoft's documentation for the va routines shows
><stdio.h> being #included (which would, of course, take care of
>the problem), but I don't think I should have to.  What sayeth
>the pANS?  I know it guarantees you can #include standard header
>files multiple times (a desirable property), but does it ever say
>you have to #include one before you can #include another?  (This
>would not be desirable.)

No, it should not matter what order you include the header files
anymore.  That is the reason for the ability to include headers
multiple times.  If a header file needs definitions which are
in another header, it should include that header.

However, as mentioned before, if you are calling a routine which
uses variable arguments, a prototype must be in scope.  You must
make sure that you include the prototype for any variable
argument functions you call.  Most of these are in stdio or
stdlib.

-- 
Mark H. Colburn                  "Look into a child's eye;
Minnetech Consulting, Inc.        there's no hate and there's no lie;
mark@jhereg.mn.org                there's no black and there's no white."

rex@aussie.UUCP (Rex Jaeschke) (04/10/89)

> This strikes me as a bug.

I believe it is in an ANSI-conformant implementation.

> but does it ever say
> you have to #include one before you can #include another?

No. Every standard header must be self-sufficient (there may be notable 
exceptions documented there) - it can't really #include another
standard header itself since NULL, for example, is only defined when
one of the 5 or 6 standard headers it is defined in, is included by
the programmer.  ANSI places no requirement you include stdio before
using stdarg and requiring you to do so MUST be non-standard.

A std header could only include another std header as long as it 
could undo every name brought in with it after it used those it 
needed, and that is generally impossible, certainly for structure 
templates and typedefs since there is no way to forget about them once 
declared.

A similar situation occurs with MSF V5.1 in assert.h. assert calls 
fprintf which requires stderr, a macro only defined in stdio. 
(Actually, MSf's assert needs quite a bit of surgery to be 
conformant.)

Rex

----------------------------------------------------------------------------
Rex Jaeschke     | C Users Journal     |  Journal of C Language Translation
(703) 860-0091   | DEC PROFESSIONAL    |1810 Michael Faraday Drive, Suite 101
uunet!aussie!rex | Programmers Journal |     Reston, Virginia 22090, USA
----------------------------------------------------------------------------