vprintf不使用va_list中的项目

时间:2014-10-22 19:10:11

标签: c++ c printf variadic-functions

我正在尝试编写printf的变体,其中正在打印的项目和正在打印的格式是调用中的相邻参数,如...

print(2, "%s", "hello", "%.5u", 25);

我研究了var args并想出了......

void print(int count, ...)
{
    va_list varg;
    va_start(varg, count);

    while(count-- > 0)
    { 
      char* format = va_arg(varg, char*);
      vprintf(format, varg);
    }               

    va_end(varg);
}

似乎vprintf没有消耗它在堆栈中使用的项目。我的输出是

hellohello

我相信这也正在扩大

printf("%s", "hello);
printf("hello");

那么我错误的是vprintf并没有消费"你好"从arg列表?

更新:根据以下评论

void print(int count, ...)
{
    va_list varg;
    va_start(varg, count);

    while(count-- > 0)
    { 
      char* format = va_arg(varg, char*);
      void* arg    = va_arg(varg, void*);
      printf(format, arg);
    }               

    va_end(varg);
}

这似乎完成了工作。

2 个答案:

答案 0 :(得分:1)

va_list只是一个地址(在典型的实现中)。它通过值传递给函数,因此调用函数中的原始函数是未修改的。

答案 1 :(得分:1)

你在这里做的是未定义的行为。在C99标准第7.15节第3段中,它说:

  

声明的类型是va_list,它是适合的对象类型   保存宏va_startva_arg所需的信息,   va_endva_copy。如果访问不同的参数是   希望,被调用的函数应声明一个对象(通常   在本子条款中称为ap,类型为va_list。的的   对象ap可以作为参数传递给另一个函数;如果说   函数使用参数va_arg调用ap宏,值为   调用函数中的ap是不确定的,应该传递给   在进一步引用va_end之前的ap宏。

在这里,您将va_list变量varg传递给函数vprintf,该函数在内部调用va_arg。因此,在它返回后,您不能再使用varg。在对其进行任何其他操作之前,您需要在其上调用va_end。相反,您在循环的下一次迭代中使用它而不先调用va_end。所以你遇到了未定义的行为。