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); }
解决方法
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
andva_copy
macros
shall be matched by a corresponding invocation of theva_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参数的版本.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。