How to properly replace sprintf_s by sprintf in C++03?

半城伤御伤魂 提交于 2020-06-26 03:48:31

问题


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?


回答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 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.



来源:https://stackoverflow.com/questions/54238576/how-to-properly-replace-sprintf-s-by-sprintf-in-c03

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!