20

如果我有一个 va_list 我知道如何提取它的所有元素:

void printInts(int n,...)
{
    va_list va;
    va_start(va, n);
    for(unsigned int i=0; i<n; i++)
    {
        int arg=va_arg(va, int);
        printf("%d",arg);
    }
    va_end(va);
} 

因此,当我调用 printInts(3,1,2,3) 时,va_list 会填充所有参数。
但是如何在不使用 va_start 的情况下手动填充 va_list?我的意思是我想要类似的东西:

va_list va;
push_arg(va, int, 5); // And so on until I fill all parameters
...

我需要这个,因为有一个函数接受 va_list 作为参数,我不知道如何填充所有参数的 va_list。

4

5 回答 5

19

无法显式填充 va_list。

您应该编写一个包装函数。假设您需要调用函数 foo,而不是手动填写 va_list,而是定义一个新函数,如下所示:

void call_foo(int arg1, ...)
{
   va_list ap;
   va_start(ap, arg1);
   foo(arg1, ap);
   va_end(ap);
}

现在你可以调用foo,它需要一个 va_list,但是你喜欢,例如 call_foo(1,2,3,4);, call_foo(1, 1, "Hello"); 等等

这将只允许您在编译时指定参数,您不能在运行时构建参数。

于 2012-12-04T13:19:53.940 回答
13

通常,这些功能成对出现。如果你有一个“va-accepting”功能,很容易创建另一个:

void printInts_v(int n, va_list ap)
{
    unsigned int i=0;
    for(i=0; i<n; i++)
    {
        int arg=va_arg(ap, int);
        printf("%d", arg);
    }
}

这个函数可以这样调用:

void printInts(int n,...)
{
    va_list ap;
    va_start(ap, n);
    printInts_v(n, ap);
    va_end(va);
}

但我不认为有一种方法可以便携式预填充以va_list供以后使用。

但是,如果您使用一种架构并且可移植性不是问题,那么您可以自己制作一些东西。具体如何做到这一点是特定于平台的。

于 2012-12-04T13:16:27.850 回答
0

我认为没有标准化的方法可以做到这一点。另一方面,这样的预填充va_list将毫无用处,因为也无法“查询”它以获取可用参数的数量和类型。

于 2012-12-04T13:14:47.603 回答
0

由于其他回复表明这是不可能的(这将是在下一个版本的语言设计中添加它的一个很好的理由),唯一可移植的可能性是

  • 检查文档两次以调查您是否没有错过或误解有关您尝试使用的框架的某些内容:我在这里遇到了完全相同的问题,它出现在我没有使用正确的调用的答案中正在尝试做;

  • 为自己编写一个函数,该函数将指针数组作为参数而不是 va_list 并将问题拆分为多个调用(并非总是可能);或者

  • 假设您尝试使用的框架设计不佳...

于 2019-05-07T11:55:59.527 回答
0

将函数拆分为多个调用适用于printf系列 - 在 Kernighan & Ritchie 中有这样的代码,大致如下:

void printf_OclFile(struct OclFile* self, char* f, void* sq[])
{ int n = length(sq);
  if (n == 0 || self->actualFile == NULL) 
  { return; }

  void* ap; 
  char* p = f; 
  int i = 0; 

  char* sval; 
  int ival; 
  double dval; 

  ap = sq[0]; 
  for ( ; *p != '\0' && i < n; p++)
  { if (*p != '%')
    { char* p0 = subString(p,1,1); 
      fputs(p0, self->actualFile); 
      continue; 
    } 

    p++; /* Points to flag after % */ 

    switch (*p)
    { case 'd' : 
        ival = *((int*) sq[i]); 
        i++; 
        fprintf(self->actualFile, "%d", ival);
        break; 
      case 'f' : 
        dval = *((double*) sq[i]); 
        i++; 
        fprintf(self->actualFile, "%f", dval); 
        break; 
      case 's' : 
        sval = ((char*) sq[i]); 
        i++; 
        fprintf(self->actualFile, "%s", sval); 
        break;
      default : 
        char* p0 = subString(p,1,1); 
        fputs(p0, self->actualFile);
        break; 
    }
  } 
}
于 2021-10-24T18:13:14.987 回答