从哪个版本的 Visual Studio 开始,vsnprintf 大多符合标准? [英] Starting at what version of Visual Studio is vsnprintf mostly standard-conformant?
问题描述
根据微软关于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, thenbuffer
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 typeint
;
并且我们希望一致性包括(除了标称输入的基本功能)这些要求(由 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):
- 不产生未定义的行为(包括调用 Microsoft 的无效参数处理程序)在上述假设下;
- 当
buffer==NULL
和count==0
时返回要写入的长度(不包括终止空字符),从而允许preflight确定长度输出; - 当
buffer!=NULL
和count>0
并且返回的结果为非负时,总是用终止空字符填充输出字符串,包括由于截断的输出小count
.
- not producing undefined behavior (including invoking Microsoft's invalid parameter handler) under the above assumptions;
- returning the length to be written (not including terminating null character) when
buffer==NULL
andcount==0
, thus allowing pre-flight to determine the length of the output; - always padding the output string with a terminating null character when
buffer!=NULL
andcount>0
and the result returned is non-negative, including for truncated output due to smallcount
.
注意评论:我愿意承认缺乏限制
限定符仍然在大多数符合标准的允许范围内.
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.
文档中的措辞也明确暗示 vsnprintf
在 buffer==NULL
和 count==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.
如果 buffer
或 format
为 NULL
,或者 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屋!