[comp.lang.c] varargs functions: calling and prototyping

mark@DRD.Com (Mark Lawrence) (07/26/90)

I'm using gcc 1.37 or so on a Sun SparcStation running 4.0.3.

I've got a function whose first three arguments should always be provided
but the rest of the arguments will be handed to vsprintf for formatting.

The function itself looks like:

#include <stdio.h>
#include <varargs.h>
#include <alarms.h> /* which includes a function prototype for this func */

#define AlarmBufSz 1024
static char     buf[AlarmBufSz];

/*VARARGS0*/
void
ReportAlarm(va_alist)
va_dcl
{
    va_list         args;
    AlarmType       alarm;
    char           *source;
    char           *fmt;

    va_start(args);
    source = va_arg(args, char *);
    alarm = va_arg(args, AlarmType);
    fmt = va_arg(args, char *);
    (void) vsprintf(buf, fmt, args);
    va_end(args);
	/* and stuff ... */
}

alarms.h looks like:

#ifndef ALARMS_H
#define ALARMS_H

typedef enum {
    alNone, alFoo,
    alLastAlarm
}               AlarmType;
/* void ReportAlarm(char * source, AlarmType alarm, char * fmt, ...) */
void ReportAlarm();
#endif              /* ALARMS_H */

My questions are:

1) do I need to provide a terminating NULL when calling this function
(I've seen it done int the Thom Plum notes on the Draft C Standard, but
I've tried it in Saber without and it *seems* to work)

2) how do I prototype it?  I tried the above commented out prototype and
when compiling function, gcc gripes that it doesn't match its prototype
and quits.

dkeisen@Gang-of-Four.Stanford.EDU (Dave Eisen) (07/26/90)

In article <1990Jul25.195944.9238@DRD.Com> mark@drd.Com (Mark Lawrence) writes:
>
>I've got a function whose first three arguments should always be provided
>but the rest of the arguments will be handed to vsprintf for formatting.
>
>The function itself looks like:
>
[The K&R version of the function omitted for brevity]

#include <stdio.h>
#include <stdarg.h> /* varags is used in the K&R world, it doesn't work with
                       prototypes */
#include <alarms.h> /* which includes a function prototype for this func */

#define AlarmBufSz 1024
static char     buf[AlarmBufSz];

/* The definition of the function matches the prototype given in alarm.h */
/* This prototype is                                                     */
/* void ReportAlarm (char *source, AlarmType alarm, char *fmt, ...);     */

/*VARARGS3*/
void
ReportAlarm(char *source, AlarmType alarm, char *fmt, ...)
{
    va_list         args;

    va_start(args, format); /* va_start now takes the last required function
                               parameter as its second argumnet. */
    (void) vsprintf(buf, fmt, args);
    va_end(args);
/* Other stuff ... */
}




--
Dave Eisen                      	    Home: (415) 323-9757
dkeisen@Gang-of-Four.Stanford.EDU           Office: (415) 967-5644
1447 N. Shoreline Blvd.
Mountain View, CA 94043

karl@haddock.ima.isc.com (Karl Heuer) (07/27/90)

In article <1990Jul25.195944.9238@DRD.Com> mark@drd.Com (Mark Lawrence) writes:
>[A function defined with the <varargs.h> macros fails to match its prototype]

Don't use <varargs.h> in ANSI C.  Use <stdarg.h> instead.

>do I need to provide a terminating NULL when calling this function

Not in this case.  The function that ultimately parses the variadic part is
vsprintf, and it uses the format string, rather than a sentinel value, to
detect the end of the list.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint