可变长度参数列表错误。

3

许多年前我写了一个自定义的打印函数,声明如下:

void my_printf(char *format_string, ... )
{
    // too complex to list here
}

我可以这样调用它:

my_printf("Number of apples = %d\n",apple);

这个函数一直运行得非常完美。现在我想创建一个包装函数,它在开头带上一个额外的整数,就像这样:

void my_printf_extra(int extra,char *format_string, ... )

可以像这样调用:

my_printf_extra(debug_level,"Number of apples = %d\n",apple);

我希望包装函数能够以类似以下方式调用原始函数:
void my_printf_extra(int extra,char *format_string, ... )
{
    if (extra == some_test)
    {
        my_printf(** not quite sure what goes here **);
    }
}

我的猜测是:

void my_printf_extra(int extra,char *format_string, ... )
{
    va_list vptr;

    if (extra == some_test)
    {
        va_start(vptr,format_string);
        my_printf(format_string,vptr);
        va_end(vptr);
    }
}

但是它没有起作用。在我的最终输出中,我看到


Number of apples = -46467968

当真实值为1时,我看到类似于某些垃圾数字的东西。调用my_printf_extra并传入字符串时也会出现类似的垃圾。我怀疑我的va_list处理有问题,但我无法确定具体是哪里出了问题。

编辑: my_printf()非常灵活,可以打印到各种不同的位置。有时它只是将文本附加到富编辑控件窗口中。这完全取决于各种标志以及正在打印的内容的内容。


va_list 传递到另一个函数不会填充参数,就像它们已经被传递一样。在这里一个合理的解决方案可能是将现有的 my_printf 简化为初始化一个 va_list 并将其传递给 my_printf_core,后者完成其余的工作。然后您的 my_printf_extra 可以调用 my_printf_core 而不是 my_printf。(my_printf_core 可以等同于标记原件中提到的 vfprintf,因此基本上是相同的解决方案,除非您需要在 my_printf_core 中进行自定义。) - Eric Postpischil
@Jean-Francois Fabre:我不明白重复内容如何有所帮助。这段代码与我的有缺陷的原始代码完全相同。 - Mick
请查看先前评论的编辑。 - Mick
我已经解决了我的错误,但无法在此处提供答案,因为该问题已被标记为重复。 - Mick
OT: 我希望在 my_printf(const char *format_string, ... ) 中使用 const - chux - Reinstate Monica
显示剩余4条评论
1个回答

4

my_printf并不需要va_list,因此您不能将其传递给它。

在这种情况下使用宏是有意义的:

#define my_printf_extra(extra, format_string, ... ) \
do {\
    if ((extra) == some_test)\
    {\
        my_printf((format_string), __VA_ARGS__);\
    }\
} while (0)
< p > __VA_ARGS__ 宏替换了所有额外的参数。请注意,这需要支持C99的编译器。< /p > < p > 或者,您可以修改 my_printf 来添加额外的逻辑,将名称更改为内部名称,然后定义 my_printfmy_printf_extra 作为调用内部函数的宏: < /p >
void my_printf_impl(int extra, char *format_string, ... )
{
    if (extra != some_test) {
        return;
    }

    ...
}

#define EXTRA_DEFAULT 0
#define my_printf(format_string, ...) \
    my_printf_impl(EXTRA_DEFAULT, format_string, __VA_ARGS__)
#define my_printf_extra(extra, format_string, ...) \
    my_printf_impl(extra, format_string, __VA_ARGS__)

这是否与C89兼容? - Jean-François Fabre
@Jean-FrançoisFabre 我不这么认为。__VA_ARGS__是在C99中引入的。 - dbush

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接