C - Sprintf的变量参数?

时间:2017-03-30 22:01:59

标签: c variadic-functions

我有一个功能;

void foo(const char* format, ...)
{
    char buffer[1080];

    // Supposed way to handle C Variable Arguments?
    va_list argptr;
    va_start(argptr, format);
    sprintf(buffer, format, argptr);
    va_end(argptr);

    printf_s("%s.\n", buffer);
}

int main()
{
    int val = 53;
    foo("%d", val);
}

每次我运行这个时,我都会得到每次运行时都会改变的大量数字。 122533605306452等。我不明白为什么。

这是我的sprintf电话的问题,还是我va_list argptr;的做法?我的buffer太大了吗?

感谢。

1 个答案:

答案 0 :(得分:6)

您显然尝试使用的技术表明您需要vsprintf(或更好,vsnprintf

va_list argptr;
va_start(argptr, format);
vsnprintf(buffer, sizeof buffer, format, argptr);
va_end(argptr);

这就是v...组中此类函数存在于标准库中的原因。

根据您的方式调用sprintf毫无意义 - 它不能与外部提供的va_list一起使用。

如果要实现可变大小的缓冲区,可以按照以下方式执行:

void foo(const char* format, ...)
{
    static char *buffer;
    static size_t buffer_size;

    va_list argptr;
    va_start(argptr, format);
    int length = vsnprintf(buffer, buffer_size, format, argptr);
    va_end(argptr);

    if (length + 1 > buffer_size)
    {
      buffer_size = length + 1;
      buffer = realloc(buffer, buffer_size);
      /* Yes, `realloc` should be done differently to properly handle
         possible failures. But that's beside the point in this context */

      va_start(argptr, format);
      vsnprintf(buffer, buffer_size, format, argptr);
      va_end(argptr);
    }

    printf("%s.\n", buffer);
}

当然,您可以将内存管理策略更改为不同的内容,例如在第一次调用中使用512字节的固定本地缓冲区,然后在第二次调用中使用临时动态分配的缓冲区512证明是不够的。等等...