从哪个版本的 Visual Studio 开始,vsnprintf 大多符合标准? [英] Starting at what version of Visual Studio is vsnprintf mostly standard-conformant?

查看:38
本文介绍了从哪个版本的 Visual Studio 开始,vsnprintf 大多符合标准?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据微软关于vsnprintf的文档,至少从 Visual Studio 2003 版起,该函数就是 C(++) 运行时库的一部分.

According to Microsoft's documentation for vsnprintf, that function is part of the C(++) Run-Time Library since at least the 2003 edition of Visual Studio.

int vsnprintf( char *buffer,        // Storage location for output
               size_t count,        // Maximum number of characters to write
               const char *format,  // Format specification
               va_list argptr )     // Pointer to list of other arguments

我问:对于哪些版本的 Visual Studio 是符合 C99 标准 (ISO/IEC 9899:1999),假设

I'm asking: for which versions of Visual Studio is the vsnprintf implementation of the bundled C(++) RTL for x86 and x64 in conformance with the C99 standard (ISO/IEC 9899:1999), assuming

  • #define _CRT_SECURE_NO_WARNINGS#include 之前执行,这是现代版本的 Visual Studio RTL 所必需的;
  • 如果 count 大于零,则 buffer 是一个指向(至少)count 个可写字符的指针;
  • 格式不是 NULL 并且符合 Microsoft 的格式适用于特定 RTL 版本的规范语法
  • count 的值和要产生的字符数都足够小以适合类型 int;
  • #define _CRT_SECURE_NO_WARNINGS is performed before #include <stdio.h>, which is required for modern versions of Visual Studio RTL;
  • if count is greater than zero, then buffer is a pointer to (at least) count writable characters;
  • format is not NULL and conforms to Microsoft's Format Specification syntax as applicable to the particular version of the RTL;
  • the value of count and the number of characters to produce are both small enough to fit type int;

并且我们希望一致性包括(除了标称输入的基本功能)这些要求(由 snprintf 的标准规范暗示,vsnprintf 引用):

and we want conformance to include (beside basic functionality for nominal input) these requirements (implied by the standard's specification of snprintf, which vsnprintf references):

  1. 不产生未定义的行为(包括调用 Microsoft 的无效参数处理程序)在上述假设下;
  2. buffer==NULLcount==0时返回要写入的长度(不包括终止空字符),从而允许preflight确定长度输出;
  3. buffer!=NULLcount>0 并且返回的结果为非负时,总是用终止空字符填充输出字符串,包括由于截断的输出小count.
  1. not producing undefined behavior (including invoking Microsoft's invalid parameter handler) under the above assumptions;
  2. returning the length to be written (not including terminating null character) when buffer==NULL and count==0, thus allowing pre-flight to determine the length of the output;
  3. always padding the output string with a terminating null character when buffer!=NULL and count>0 and the result returned is non-negative, including for truncated output due to small count.

注意评论:我愿意承认缺乏限制限定符仍然在大多数符合标准的允许范围内.

Note following comment: I'm willing to admit the lack of restrict qualifiers as still within allowance for mostly standard-conformant.

文档在 (3.) 方面留下了不明确的一致性;据我所知,与 Visual Studio Community 2015 捆绑在一起的实现很好,但不是全部.

The documentation leaves conformance ambiguous with respect to (3.); the implementation bundled with Visual Studio Community 2015 is fine as far as I can tell, but not all are.

如果末尾有空间(即,如果要写入的字符数小于count),则缓冲区将以空字符结尾.

If there is room at the end (that is, if the number of characters to write is less than count), the buffer will be null-terminated.

文档中的措辞也明确暗示 vsnprintfbuffer==NULLcount==0 ;但文档的这些部分似乎是错误的:

The documentation also has wording unambiguously implying that vsnprintf is not in conformance with the C99 standard with respect to (1.) and (2.) when buffer==NULL and count==0 ; but theses parts of the documentation seemingly turn out to be wrong:

如果要写入的字符数大于 count,则这些函数返回 -1,表示输出已被截断.

if the number of characters to write is greater than count, these functions return -1 indicating that output has been truncated.

如果 bufferformatNULL,或者 count 小于或等于 0,则这些函数调用无效参数处理程序

If buffer or format is NULL, or if count is less than or equal to zero, these functions invoke the invalid parameter handler


测试代码:


Test code:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdarg.h>

int f( char *buffer,
       size_t count,
       const char *format,
       ...
     )
{
    va_list vArgs;
    int vRes;
    va_start(vArgs, format);
    vRes = vsnprintf( buffer, count, format, vArgs);
    va_end(vArgs);
    return vRes;
}

int main(void)
{
    char vBuf[6];
    int j, count;
#ifdef _MSC_VER
    printf("_MSC_VER = %ld\n",(long)(_MSC_VER));
#else
    printf("_MSC_VER is undefined\n");
#endif
    printf("f(NULL,0,\"%%d\",777):%3d\n", f(NULL,0,"%d",777));
    for(count=0 ;count<=sizeof(vBuf); ++count)
    {
        for(j=0; j<sizeof(vBuf)-1; ++j)
            vBuf[j] = '!';
        vBuf[j] = 0;
        j =  f(vBuf,count,"%d",777);
        printf("f(vBuf,%d,\"%%d\",777):%3d  vBuf: \"%s\"\n",count,j,vBuf);
    }
    return 0;
}

在我安装的 Visual Studio Community 2015 下提供

giving under my install of Visual Studio Community 2015

_MSC_VER = 1900
f(NULL,0,"%d",777):  3
f(vBuf,0,"%d",777):  3  vBuf: "!!!!!"
f(vBuf,1,"%d",777):  3  vBuf: ""
f(vBuf,2,"%d",777):  3  vBuf: "7"
f(vBuf,3,"%d",777):  3  vBuf: "77"
f(vBuf,4,"%d",777):  3  vBuf: "777"
f(vBuf,5,"%d",777):  3  vBuf: "777"
f(vBuf,6,"%d",777):  3  vBuf: "777"

在一些 Visual Studio 2008 安装下(我相信 SP1 + PSDK 7.1)

and under some install of Visual Studio 2008 (I believe SP1 + PSDK 7.1)

_MSC_VER = 1500
f(NULL,0,"%d",777):  3
f(vBuf,0,"%d",777): -1  vBuf: "!!!!!"
f(vBuf,1,"%d",777): -1  vBuf: "7!!!!"
f(vBuf,2,"%d",777): -1  vBuf: "77!!!"
f(vBuf,3,"%d",777):  3  vBuf: "777!!"
f(vBuf,4,"%d",777):  3  vBuf: "777"
f(vBuf,5,"%d",777):  3  vBuf: "777"
f(vBuf,6,"%d",777):  3  vBuf: "777"

注意缺少终止空字符,特别是对于 count==3,即使输出是正数.

Notice the lack of terminating null character in particular for count==3, even though the output is positive.

推荐答案

你现在提到的页面给出了答案:

The very page you mention now gives the answer:

从 Visual Studio 2015 和 Windows 10 中的 UCRT 开始,vsnprintf 不再与 _vsnprintf 相同.vsnprintf函数符合C99标准;_vnsprintf 保留下来是为了与旧的 Visual Studio 代码向后兼容.

Beginning with the UCRT in Visual Studio 2015 and Windows 10, vsnprintf is no longer identical to _vsnprintf. The vsnprintf function complies with the C99 standard; _vnsprintf is retained for backward compatibility with older Visual Studio code.

并且您的输出与 _vsnprintf:

_vsnprintf 和 _vsnwprintf 函数在写入的字符数小于等于 count 时返回写入的字符数;如果要写入的字符数大于 count,则这些函数返回 -1,表示输出已被截断.

Both _vsnprintf and _vsnwprintf functions return the number of characters written if the number of characters to write is less than or equal to count; if the number of characters to write is greater than count, these functions return -1 indicating that output has been truncated.

这篇关于从哪个版本的 Visual Studio 开始,vsnprintf 大多符合标准?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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