从什么版本的 Visual Studio 开始,vsnprintf 最符合标准?
Starting at what version of Visual Studio is vsnprintf mostly standard-conformant?
根据 Microsoft's documentation for vsnprintf
,该函数是 C(++) 运行-Time 库的一部分,至少从 Visual Studio.
的 2003 版开始
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 标准的 x86 和 x64 捆绑 C(++) RTL 的 vsnprintf
实现(ISO/IEC 9899:1999), 假设
#define _CRT_SECURE_NO_WARNINGS
在 #include <stdio.h>
之前执行,这是现代版本的 Visual Studio RTL 所必需的;
- 如果
count
大于零,则 buffer
是指向(至少)count
个可写字符的指针;
- 格式不是
NULL
并且符合 Microsoft's Format Specification syntax 适用于特定版本的 RTL;
count
的值和要生成的字符数都足够小以适合类型 int
;
并且我们希望一致性包括(除了标称输入的基本功能之外)这些要求(由 snprintf
的标准规范暗示,vsnprintf
引用):
- 在上述假设下不会产生未定义的行为(包括调用Microsoft's invalid parameter handler);
- 在
buffer==NULL
和count==0
时返回要写入的长度(不包括终止空字符),从而允许飞行前确定输出的长度;
- 总是在
buffer!=NULL
和 count>0
时用终止空字符填充输出字符串并且返回的结果是非负数,包括由于小 count
导致的截断输出。
注意 之后:我愿意承认缺少 restrict
限定词,因为大多数符合标准的人仍然在允许范围内。
文档对 (3.) 的一致性含糊不清;据我所知,与 Visual Studio Community 2015 捆绑在一起的实现很好,但并非所有都是。
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
方面不符合 C99 标准的 (1.) 和 (2.) ;但文档的这些部分似乎是错误的:
if the number of characters to write is greater than count
, these functions return -1 indicating that output has been truncated.
If buffer
or format
is NULL
, or if count
is less than or equal to zero, these functions invoke the invalid parameter handler
测试代码:
#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
下捐赠
_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)
_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
,即使输出是正数。
您提到的页面现在给出了答案:
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一致:
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.
根据 Microsoft's documentation for vsnprintf
,该函数是 C(++) 运行-Time 库的一部分,至少从 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 标准的 x86 和 x64 捆绑 C(++) RTL 的 vsnprintf
实现(ISO/IEC 9899:1999), 假设
#define _CRT_SECURE_NO_WARNINGS
在#include <stdio.h>
之前执行,这是现代版本的 Visual Studio RTL 所必需的;- 如果
count
大于零,则buffer
是指向(至少)count
个可写字符的指针; - 格式不是
NULL
并且符合 Microsoft's Format Specification syntax 适用于特定版本的 RTL; count
的值和要生成的字符数都足够小以适合类型int
;
并且我们希望一致性包括(除了标称输入的基本功能之外)这些要求(由 snprintf
的标准规范暗示,vsnprintf
引用):
- 在上述假设下不会产生未定义的行为(包括调用Microsoft's invalid parameter handler);
- 在
buffer==NULL
和count==0
时返回要写入的长度(不包括终止空字符),从而允许飞行前确定输出的长度; - 总是在
buffer!=NULL
和count>0
时用终止空字符填充输出字符串并且返回的结果是非负数,包括由于小count
导致的截断输出。
注意 restrict
限定词,因为大多数符合标准的人仍然在允许范围内。
文档对 (3.) 的一致性含糊不清;据我所知,与 Visual Studio Community 2015 捆绑在一起的实现很好,但并非所有都是。
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
方面不符合 C99 标准的 (1.) 和 (2.) ;但文档的这些部分似乎是错误的:
if the number of characters to write is greater than
count
, these functions return -1 indicating that output has been truncated.If
buffer
orformat
isNULL
, or ifcount
is less than or equal to zero, these functions invoke the invalid parameter handler
测试代码:
#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
下捐赠_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)
_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
,即使输出是正数。
您提到的页面现在给出了答案:
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一致:
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.