链接可变函数调用

chaining variadic function calls

一个printf从一个参数数量可变的函数调用类函数很容易——只需使用这些函数的v版本(vprintfvsprintfCString::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* 的函数,然后 然后 将每个函数包装在基于省略号的可变参数函数中。