Today both snprintf
and vsnprintf
should be available everywhere with the exception of Windows with MSVC12 and older. The simplest way for you is to provide snprintf
/vsnprintf
on Windows where it is not available.
Windows provides function _vsnprintf_s
which is already similar to vsnprintf
, but has following important differences with regards to what happens when provided buffer is too small:
- Buffer content depends on the additional
count
argument which does not exist in vsnprintf
. To get vsnprintf
behavior you can pass _TRUNCATE
here.
-1
is returned instead of number of characters required. This can be fixed by using _vscprintf
function which only needs to be called if previous call to _vsnprintf_s
has failed.
Additionally those functions do not support format specifiers added in C99 such as %zd
. This cannot be easily resolved, you will have to avoid using them.
Code below:
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
{
int r = -1;
if (size != 0)
{
va_list args_copy;
va_copy(args_copy, args);
r = _vsnprintf_s(buf, size, _TRUNCATE, fmt, args_copy);
va_end(args_copy);
}
if (r == -1)
{
r = _vscprintf(fmt, args);
}
return r;
}
int snprintf(char *buf, size_t size, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int r = vsnprintf(buf, size, fmt, args);
va_end(args);
return r;
}
Note: Windows also provides _vsnprintf
which looks better suited for this implementation, but it does not terminate the resulting string. If you want to use it, you should be careful.