函数的可变参数是否需要va_start?

时间:2014-03-28 03:30:24

标签: c variadic-functions variadic-macros

我正在阅读Linux编程接口文本并显示此功能来处理错误。在手册页(man stdarg)中,必须首先调用va_start来初始化ap以供va_arg()va_end使用。

那么为什么在这个函数中没有va_start

static void
outputError(Boolean useErr, int err, Boolean flushStdout,
        const char *format, va_list ap) 
{
#define BUF_SIZE 500
    char buf[BUF_SIZE], userMsg[BUF_SIZE], errText[BUF_SIZE];

    vsnprintf(userMsg, BUF_SIZE, format, ap);

    if (useErr)                                                                               
        snprintf(errText, BUF_SIZE, " [%s %s]",
                (err > 0 && err <= MAX_ENAME) ?
                ename[err] : "?UNKNOWN?", strerror(err));
    else
        snprintf(errText, BUF_SIZE, ":");

    snprintf(buf, BUF_SIZE, "ERROR%s %s\n", errText, userMsg);

    if (flushStdout)
        fflush(stdout);       /* Flush any pending stdout */
    fputs(buf, stderr);
    fflush(stderr);           /* In case stderr is not line-buffered */
}

2 个答案:

答案 0 :(得分:2)

va_list ap作为参数传递给函数outputError(),它必须在va_start(或调用者的调用者等)的调用者中由outputError()初始化。< / p>

要回答您的主要问题,是的,va_start是必需的,但不一定在当前使用vp_list的函数中。 va_end也一样。

答案 1 :(得分:1)

  

那么为什么在这个函数中没有va_start

以下是使用outputError()的其中一个地方:

void
errMsg(const char *format, ...)
{
    va_list argList;
    int savedErrno;
    savedErrno = errno;
    /* In case we change it here */
    va_start(argList, format);
    outputError(TRUE, errno, TRUE, format, argList);
    va_end(argList);
    errno = savedErrno;
}

我认为这清楚地回答了你的问题。