链接可变参数函数调用

YeP*_*IcK 1 c c++ variadic-functions

printf类函数从不同的参数个数函数调用很容易足以让-只使用一个v的那些功能(-version 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;
}
Run Code Online (Sandbox Code Playgroud)

示例输出如下:

direct works just fine: 1
indirect produces garbage: 1951661256
Run Code Online (Sandbox Code Playgroud)

我觉得我缺少明显的东西,但到目前为止还不能弄清楚。请帮助我修复它,以便无论我调用direct还是chained代码都能正常工作。

将问题标记为C / C ++,但我更喜欢C ++答案(如果有所不同)

Sto*_*ica 5

我觉得我遗漏了一些明显的东西,但到目前为止还无法弄清楚

你做到了 这实际上是您开始的:“仅使用这些函数的v版本”。这些函数获得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);
}
Run Code Online (Sandbox Code Playgroud)

这样拆分的一个很好的新兴特性direct是,您可以更好地分离关注点。包装器会处理va_list相关的位,而v函数仅关心列表需要完成的工作,因此可以在此处重用。


编辑前注意:顺便说一句,如果确实需要C兼容性,则函数原型需要使用逗号将最后一个参数与省略号分开。您使用的语法仅是C ++。