sprintf_s
是Microsoft函数sprintf
的实现,其中他们修补了一个缺陷,并添加了一个参数以取一个边界值,其中该函数只能写。
在C++11
中引入了等效项:snprintf
。但是在这里,我们谈论的是C++03
语法。
签名:
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);
在功能上,sprintf_s
比sprintf
更先进,因为它避免了溢出。
但是sprintf_s
仅适用于Microsoft!
如果要将使用C++03
编写的sprintf_s
代码移植回POSIX兼容语法该怎么办?
答案 0 :(得分:2)
今天,snprintf
和vsnprintf
都应随处可用,但MSVC12和更早版本的Windows除外。最简单的方法是在不可用的Windows上提供snprintf
/ vsnprintf
。
Windows提供的功能_vsnprintf_s
与vsnprintf
类似,但是在提供缓冲区太小时会发生以下重要变化:
count
中不存在的附加vsnprintf
参数。要获得vsnprintf
的行为,您可以在此处传递_TRUNCATE
。-1
而不是所需的字符数。可以使用_vscprintf
函数来解决此问题,该函数仅在先前对_vsnprintf_s
的调用失败时才需要调用。此外,这些功能不支持C99中添加的格式说明符,例如%zd
。这不能轻易解决,您将不得不避免使用它们。
以下代码:
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;
}
注意:Windows还提供了_vsnprintf
,它看起来更适合此实现,但是它不会终止结果字符串。如果要使用它,请务必小心。