Hatefiend
Hatefiend

Reputation: 3596

C - Variable Argument with Sprintf?

I have a function;

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);
}

Everytime I run this, I get MASSIVE numbers that change every during each run. 12253360, 5306452, etc. I don't understand why.

Is it something with my sprintf call or is it the way I'm doing the va_list argptr;? Is my buffer too large?

Thanks.

Upvotes: 4

Views: 3243

Answers (1)

AnT stands with Russia
AnT stands with Russia

Reputation: 320631

The technique you are apparently attempting to use suggests that you need vsprintf (or, better, vsnprintf)

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

That's the very reason such functions from v... group exist in standard library.

Calling sprintf the way you do it makes no sense at all - it cannot be used with an externally supplied va_list.


If you want to implement a variable-sized buffer you can do it as follows

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);
}

You can, of course, change the memory management strategy to something different, like use a fixed local buffer of 512 bytes in the first call, and then use a temporary dynamically allocated buffer in the second call only if 512 proves to be insufficient. And so on...

Upvotes: 9

Related Questions