将可变parameter passing给另一个接受可变参数列表的函数
所以我有两个function,都有类似的论点
void example(int a, int b, ...); void exampleB(int b, ...);
现在example
调用exampleB
,但是如何在variables参数列表中传递variables而不修改exampleB
(因为这已经在其他地方使用了)。
你不能直接做; 你必须创build一个需要va_list
的函数:
#include <stdarg.h> static void exampleV(int b, va_list args); void example(int a, int b, ...) { va_list args; va_start(args, b); exampleV(b, args); va_end(args); } void exampleB(int b, ...) { va_list args; va_start(args, b); exampleV(b, args); va_end(args); } static void exampleV(int b, va_list args) { ...whatever you planned to have exampleB do... ...except it calls neither va_start nor va_end... }
你应该创build这些函数的版本,并将其传递给va_list。 以vprintf
为例:
int vprintf ( const char * format, va_list arg );
顺便说一下,许多C实现有一个内部v?printf的变化,恕我直言,应该是C标准的一部分。 确切的细节不尽相同,但是一个典型的实现将接受一个包含字符输出函数指针的结构以及说明应该发生什么的信息。 这允许printf,sprintf和fprintf都使用相同的“核心”机制。 例如,vsprintf可能是这样的:
void s_out(PRINTF_INFO * p_inf,char ch) { (*(p_inf-> destptr)++)= ch; p_inf->结果++; } int vsprintf(char * dest,const char * fmt,va_list args) { PRINTF_INFO p_inf; p_inf.destptr = dest; p_inf.result = 0; p_inf.func = s_out; core_printf(&P_INF,FMT,参数); }
然后,core_printf函数为每个要输出的字符调用p_inf-> func; 输出函数可以将字符发送到控制台,文件,string或其他东西。 如果一个实现暴露了core_printf函数(以及它使用的任何设置机制),可以用各种各样的变体来扩展它。
我也想打包printf,并在这里find了一个有用的答案:
如何将可变数量的parameter passing给printf / sprintf
我对性能一点都不感兴趣(我敢肯定,这段代码可以通过多种方式进行改进,随时都可以这么做:)),这只是为了进行一般的debugging打印,所以我这样做了:
//Helper function std::string osprintf(const char *fmt, ...) { va_list args; char buf[1000]; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args ); va_end(args); return buf; }
然后我可以这样使用
Point2d p; cout << osprintf("Point2d: (%3i, %3i)", px, py); instead of for example: cout << "Point2d: ( " << setw(3) << px << ", " << py << " )";
c ++ ostreams在某些方面很漂亮,但是如果你想用一些小的string(例如数字之间插入的括号,冒号和逗号)打印这样的内容,实际上会变得可怕。
也许在这里的池塘里扔石头,但它似乎工作相当不错的C + + 11可变模板:
#include <stdio.h> template<typename... Args> void test(const char * f, Args... args) { printf(f, args...); } int main() { int a = 2; test("%s\n", "test"); test("%s %d %d %p\n", "second test", 2, a, &a); }
至less,它适用于g++
。
根据你打包vsprintf
的评论,这被标记为C ++我会build议不要尝试这样做,但改变你的接口来使用C ++ iostreams来代替。 它们比function的print
线更有优势,例如types安全性和能够打印printf
无法处理的项目。 现在一些返工可以在未来节省大量的痛苦。
使用新的C ++ 0x标准,您可能可以使用可变参数模板来完成此操作,甚至可以将旧的代码转换为新的模板语法而不会破坏任何内容。