如何在 C++03 中用 sprintf 正确替换 sprintf_s? [英] How to properly replace sprintf_s by sprintf in C++03?

查看:128
本文介绍了如何在 C++03 中用 sprintf 正确替换 sprintf_s?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

sprintf_s 是函数 sprintf 的微软实现,他们修补了一个缺陷,添加了一个参数来获取函数被限制写入的边界值.>

C++11 中引入了一个等价物:snprintf.但在这里,我们谈论的是 C++03 语法.

签名:

count_char_written sprintf(char* string_out, const char* output_template, VARIADIC_ARGS);//和count_char_written sprintf_s(char* string_out, size_t buffer_max_size, const char* output_template, VARIADIC_ARGS);

Functionnaly,sprintf_ssprintf 更先进,因为它避免了溢出.但是 sprintf_s 只是微软的!

如果您想将用 sprintf_s 编写的 C++03 代码移植回 POSIX 兼容语法,该怎么办?

解决方案

今天,snprintfvsnprintf 应该可以在任何地方使用,除了使用 MSVC12 及更早版本的 Windows.对您来说,最简单的方法是在 Windows 上提供 snprintf/vsnprintf,而它不可用.

Windows 提供了函数 _vsnprintf_s,它已经与 vsnprintf 类似,但在提供的缓冲区太小时会发生以下重要差异:

  • 缓冲区内容取决于 vsnprintf 中不存在的附加 count 参数.要获得 vsnprintf 行为,您可以在此处传递 _TRUNCATE.
  • 返回
  • -1 而不是所需的字符数.这可以通过使用 _vscprintf 函数来解决,该函数仅在之前对 _vsnprintf_s 的调用失败时才需要调用.

此外,这些函数不支持在 C99 中添加的格式说明符,例如 %zd.这不容易解决,您必须避免使用它们.

代码如下:

int vsnprintf(char *buf, size_t size, const char *fmt, va_​​list args){int r = -1;如果(大小!= 0){va_list args_copy;va_copy(args_copy, args);r = _vsnprintf_s(buf, size, _TRUNCATE, fmt, args_copy);va_end(args_copy);}如果 (r == -1){r = _vscprintf(fmt, args);}返回 r;}int snprintf(char *buf, size_t size, const char *fmt, ...){va_list 参数;va_start(args, fmt);int r = vsnprintf(buf, size, fmt, args);va_end(参数);返回 r;}

注意:Windows 还提供了 _vsnprintf,它看起来更适合此实现,但它不会终止生成的字符串.如果你想使用它,你应该小心.

sprintf_sis 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?

解决方案

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.

这篇关于如何在 C++03 中用 sprintf 正确替换 sprintf_s?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆