问题
sprintf_s
is a Microsoft implementation of the function sprintf
where they patched a flaw, adding an argument to take a boundary value where the function is limited to write.
An equivalent was introduced in C++11
: snprintf
. But here, we are talking of C++03
syntax.
Signatures:
count_char_written sprintf(char* string_out, const char* output_template, VARIADIC_ARGS);
// and
count_char_written sprintf_s(char* string_out, size_t buffer_max_size, const char* output_template, VARIADIC_ARGS);
Functionnaly, sprintf_s
is more advanced than sprintf
, because it avoids overflows.
But sprintf_s
is Microsoft only!
What to do if you want to port back a C++03
code written with sprintf_s
to POSIX compatible syntax?
回答1:
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 invsnprintf
. To getvsnprintf
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.
来源:https://stackoverflow.com/questions/54238576/how-to-properly-replace-sprintf-s-by-sprintf-in-c03