链接可变函数调用
chaining variadic function calls
一个printf
从一个参数数量可变的函数调用类函数很容易——只需使用这些函数的v版本(vprintf
、vsprintf
、CString::FormatV
等)。但是,如果我将调用链接起来怎么办?这是简单的代码:
#include <stdarg.h>
#include <iostream>
void direct(const char * _fmt, bool _extra, ...){
va_list args;
va_start(args, _extra);
char ca[200];
vsprintf(ca, _fmt, args);
std::cout << ca << std::endl;
va_end(args);
}
void chained(const char * _fmt, ...){
va_list args;
va_start(args, _fmt);
direct(_fmt, false, args);
va_end(args);
}
int main(){
direct("direct works just fine: %d", false, 1);
chained("indirect produces garbage: %d", 1);
return 0;
}
示例输出如下:
direct works just fine: 1
indirect produces garbage: 1951661256
我觉得我遗漏了一些明显的东西,但到目前为止还想不通。请帮我修复它,这样无论我调用 direct
还是 chained
代码都能正常工作。
将问题标记为 C/C++ 但我更喜欢 C++ 答案(如果有差异的话)
I feel that I'm missing something obvious but can't figure it out thus far
你做到了。这是您实际开始的内容:"just use a v-version of those functions"。这些函数获得 v 版本的原因是允许(如您所说)链接它们。因此,如果您想为自己的类似 printf 的函数支持它,请确保遵循相同的做法:
void direct_v(const char * _fmt, bool _extra, va_list args){
char ca[200];
vsprintf(ca, _fmt, args);
std::cout << ca << std::endl;
}
void direct(const char * _fmt, bool _extra...){
va_list args;
va_start(args, _extra);
direct_v(_fmt, _extra, args);
va_end(args);
}
void chained(const char * _fmt...){
va_list args;
va_start(args, _fmt);
direct_v(_fmt, false, args);
va_end(args);
}
像这样拆分 direct
的一个不错的新兴 属性 是您可以更好地分离关注点。包装器执行 va_list
相关位,而 v-function 只关心列表需要做什么,这就是允许在这里重用的原因。
预编辑说明:顺便说一句,如果 C 兼容性确实是一个问题,函数原型需要一个逗号来将最后一个参数与省略号分开。您使用的语法仅为 C++。
您不能 链调用 C 风格的可变参数函数。唯一的方法是将 va_list
作为参数传递。这正是需要 v* 系列函数的原因。
因此,您根据 va_list
编写类似 v* 的函数,然后 然后 将每个函数包装在基于省略号的可变参数函数中。
一个printf
从一个参数数量可变的函数调用类函数很容易——只需使用这些函数的v版本(vprintf
、vsprintf
、CString::FormatV
等)。但是,如果我将调用链接起来怎么办?这是简单的代码:
#include <stdarg.h>
#include <iostream>
void direct(const char * _fmt, bool _extra, ...){
va_list args;
va_start(args, _extra);
char ca[200];
vsprintf(ca, _fmt, args);
std::cout << ca << std::endl;
va_end(args);
}
void chained(const char * _fmt, ...){
va_list args;
va_start(args, _fmt);
direct(_fmt, false, args);
va_end(args);
}
int main(){
direct("direct works just fine: %d", false, 1);
chained("indirect produces garbage: %d", 1);
return 0;
}
示例输出如下:
direct works just fine: 1
indirect produces garbage: 1951661256
我觉得我遗漏了一些明显的东西,但到目前为止还想不通。请帮我修复它,这样无论我调用 direct
还是 chained
代码都能正常工作。
将问题标记为 C/C++ 但我更喜欢 C++ 答案(如果有差异的话)
I feel that I'm missing something obvious but can't figure it out thus far
你做到了。这是您实际开始的内容:"just use a v-version of those functions"。这些函数获得 v 版本的原因是允许(如您所说)链接它们。因此,如果您想为自己的类似 printf 的函数支持它,请确保遵循相同的做法:
void direct_v(const char * _fmt, bool _extra, va_list args){
char ca[200];
vsprintf(ca, _fmt, args);
std::cout << ca << std::endl;
}
void direct(const char * _fmt, bool _extra...){
va_list args;
va_start(args, _extra);
direct_v(_fmt, _extra, args);
va_end(args);
}
void chained(const char * _fmt...){
va_list args;
va_start(args, _fmt);
direct_v(_fmt, false, args);
va_end(args);
}
像这样拆分 direct
的一个不错的新兴 属性 是您可以更好地分离关注点。包装器执行 va_list
相关位,而 v-function 只关心列表需要做什么,这就是允许在这里重用的原因。
预编辑说明:顺便说一句,如果 C 兼容性确实是一个问题,函数原型需要一个逗号来将最后一个参数与省略号分开。您使用的语法仅为 C++。
您不能 链调用 C 风格的可变参数函数。唯一的方法是将 va_list
作为参数传递。这正是需要 v* 系列函数的原因。
因此,您根据 va_list
编写类似 v* 的函数,然后 然后 将每个函数包装在基于省略号的可变参数函数中。