C/C++: Writing printf-style Functions

On January 11, 2010, in Code Monkey, by Tom

Having printf-style functions is very useful. I find myself periodically having to remember how to write variable argument functions, so I decided to just blog about it.

EDIT (4/18/2011): Simple Version That Just Prints

#include <stdarg.h>

void Foo( const char* format, ... )
{
    va_list args;
    va_start( args, format );
    vprintf( format, args );
    va_end( args );
}

End Edit

#include <stdarg.h>   // or <cstdarg>

// Hide annoying naming differences between Windows and other platforms
#ifdef WIN32
    #define my_vsnprintf _vsnprintf
#else
    #define my_vsnprintf vsnprintf
#endif

// The function
void Foo( const char* format, ... )
{
    // Parse the argument list
    va_list args;
    va_start( args, format );

    // Calculate the final length of the formatted string
    int len = my_vsnprintf( 0, 0, format, args );

    // Allocate a buffer (including room for null termination)
    char* target_string = new char[++len];

    // Generate the formatted string
    my_vsnprintf( target_string, len, format, args );

    /* Do something with the formatted string */

    // Clean up
    delete [] target_string;
    va_end( args );
}

Gotchas

We ran into a problem with vsnprintf() using the Denx Linux distro on a PowerPC processor: vsnprintf( 0, 0, format, args ) would modify the va_list, which would cause a crash on the second call to vsnprintf()… the one that does the actual formatting.  The work-around is to make a temporary copy of the va_list when determining the formatted string length:

va_list args_copy;
va_copy( args_copy, args );
int len = my_vsnprintf( 0, 0, format, args );
va_end( args_copy );

Tagged with:  

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>