【问题标题】:Variable length argument list error变长参数列表错误
【发布时间】:2018-06-28 15:22:00
【问题描述】:

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

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 中进行自定义。)
  • @Jean-Francois Fabre:我看不出副本有什么帮助。该代码与我的原始代码相同。
  • 你误读了。 1)它不一样,因为它使用vfprintf 和2)它有效。所以在一般情况下没有真正的解决方案,但使用printf 系列函数,您可以使用vfprintf
  • 我没有打印到标准输出。 my_printf 函数实际上相当复杂,可以打印到各种不同的位置或文件或图形 - 以各种颜色等 - 有时不止一个位置。取决于标志
  • 您要打印到文件吗?缓冲区?

标签: c variadic-functions


【解决方案1】:

由于my_printf 不期望va_list,因此您不能将其传递给它。

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

#define my_printf_extra(extra, format_string, ... ) \
do {\
    if ((extra) == some_test)\
    {\
        my_printf((format_string), __VA_ARGS__);\
    }\
} while (0)

__VA_ARGS__ 宏替换了所有额外的参数。请注意,这需要支持 C99 的编译器。

或者,您可以修改 my_printf 以添加额外的逻辑,将名称更改为内部名称,然后将 my_printfmy_printf_extra 定义为调用内部函数的宏:

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çoisFabre 我不这么认为。 __VA_ARGS__ 是在 C99 中引入的。
猜你喜欢
  • 1970-01-01
  • 2019-11-15
  • 1970-01-01
  • 2015-06-25
  • 1970-01-01
  • 2020-05-08
  • 2011-03-12
  • 2015-03-12
  • 2021-02-23
相关资源
最近更新 更多