c – 重复使用可变函数参数不起作用

前端之家收集整理的这篇文章主要介绍了c – 重复使用可变函数参数不起作用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个功能,试图将东西记录到控制台和日志文件,但它不起作用.第二次使用可变长度参数给垃圾写入控制台.有任何想法吗?
void logPrintf(const char *fmt,...) {
        va_list ap;    // log to logfile
        va_start(ap,fmt);
        logopen;
        vfprintf(flog,fmt,ap);
        logClose;
        va_end(ap);
        va_list ap2;   // log to console
        va_start(ap2,fmt);
        printf(fmt,ap2);
        va_end(ap2);
    }

解决方法

原始代码失败,因为它尝试使用需要使用vprintf()的printf().以面值的logopen和logClose语句为例,给出可疑点(给定符号,大概是它们是打开和关闭flog文件流的宏),代码应该是:
void logPrintf(const char *fmt,...) {
    va_list ap;
    va_start(ap,fmt);
    logopen;
    vfprintf(flog,ap);
    logClose;
    va_end(ap);
    va_list ap2;
    va_start(ap2,fmt);
    vprintf(fmt,ap2);
    va_end(ap2);
}

没有特别要求使用两个单独的va_list变量;在再次使用va_start()之前,使用va_end(),只要使用相同的两倍即可.

void logPrintf(const char *fmt,ap);
    logClose;
    va_end(ap);
    va_start(ap,ap);
    va_end(ap);
}

当va_list值传递给另一个函数(vfprintf()和vprintf())时,您应该假定它在当前函数中不再可用.调用va_end()就可以安全.

代码中不需要va_copy().它有效,但不是必需的.在其他情况下,您需要va_copy(),例如当您的函数通过va_list时,您需要处理两次列表:

void logVprintf(const char *fmt,va_list args1)
{
    va_list args2;
    va_copy(args2,args1);
    logopen;
    vfprintf(flog,args1);
    logClose;
    vprintf(fmt,args2);
    va_end(args2);
}

请注意,在这段代码中,调用代码有责任在args1上调用va_end().的确,标准说:

Each invocation of the va_start and va_copy macros
shall be matched by a corresponding invocation of the va_end macro in the same function.

由于logVprintf()函数调用va_start或va_copy来初始化args1,所以它无法在args1上合法调用va_end.另一方面,该标准要求它为args2调用va_end.

logPrintf()函数现在可以使用logVprintf()来实现:

void logPrintf(const char *fmt,...)
{
    va_list args;
    va_start(args,fmt);
    logVprintf(fmt,args);
    va_end(args);
}

这个结构 – 一个操作函数,通过一个va_list和覆盖函数获取省略号(可变参数),并将它们转换为va_list之后将其传递给操作函数 – 通常是一种很好的工作方式.迟早,您通常会发现需要使用va_list参数的版本.

猜你在找的C&C++相关文章