可移植地扩展va_list

时间:2010-10-19 13:02:04

标签: c variadic-functions

我有签名的第三方功能:

int secretfoo(int numargs, ...);

我可以直接调用它,但我真正想要的是用我的函数包装它,为它添加一些额外的参数。

假设整数的简单情况:我希望将调用secretfoo(2, 10, 20)翻译为:当我看到参数10复制它并进行调用时:secretfoo(3, 10, 10, 20)。我想在包装器中做到这一点:

int foowrapper(int numargs, ...);

此包装器分析argumetns并如上所述调用secretfoo

这可以通过va_list / va_arg等方式轻松完成吗?还有别的吗?

2 个答案:

答案 0 :(得分:3)

没有可移植的方法直接操作变量参数列表中的参数,因为它是高度平台依赖的,如何将这些参数传递给函数。在大多数硬件架构中,绝对没有办法在列表的中间或末尾插入其他参数。

如果参数数量存在实际上限,则可以通过提取foowrapper的所有参数并“手动”构建调用secretfoo的新参数列表来完成。 。
代码看起来像这样:

int foowrapper(int numarg, ...)
{
  va_list args
  int newargs[numarg*2]; /* worst case allocation */
  int numnewargs = 0;

  /* Extract the arguments */
  va_start(numarg, args);
  for (int i=0; i<numarg; i++)
  {
    newargs[numnewargs++] = va_arg(args, int);

    /* duplicate value 10 as you encounter it */
    if (newargs[numnewargs-1] == 10)
    {
      newargs[numnewargs++] = 10;
    }
  }

  /* Forward to the secretfoo function */
  switch (numnewargs)
  {
  case 0: return secretfoo(0);
  case 1: return secretfoo(1, newargs[0]);
  case 2: return secretfoo(2, newargs[0], newargs[1]);
  /* etc... */
  }
}

答案 1 :(得分:2)

我担心它无法轻松完成。 stdarg.h“定义了四个宏”(最新C standard draft):va_startva_endva_argva_copy。这些都不能用于将va_list转换回可变数量的值,而不是一个接一个。

您的第三方库应该提供了一个函数vsecretfoo(int, va_list),就像标准库对这些情况所做的那样(vprintf等。)。