C语言 snprintf 和 Visual Studio 2010
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2915672/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
snprintf and Visual Studio 2010
提问by Andrew
I'm unfortunate enough to be stuck using VS 2010 for a project, and noticed the following code still doesn't build using the non-standards compliant compiler:
我很不幸被困在使用 VS 2010 进行项目,并注意到以下代码仍然没有使用不符合标准的编译器构建:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
char buffer[512];
snprintf(buffer, sizeof(buffer), "SomeString");
return 0;
}
(fails compilation with the error: C3861: 'snprintf': identifier not found)
(编译失败并出现错误:C3861: 'snprintf': identifier not found)
I remember this being the case way back with VS 2005 and am shocked to see it still hasn't been fixed.
我记得这就是 VS 2005 的情况,并且很震惊地看到它仍然没有得到修复。
Does any one know if Microsoft has any plans to move their standard C libraries into the year 2010?
有谁知道微软是否有计划将其标准 C 库移至 2010 年?
回答by Valentin Milea
Short story:Microsoft has finally implemented snprintf in Visual Studio 2015. On earlier versions you can simulate it as below.
小故事:Microsoft 终于在 Visual Studio 2015 中实现了 snprintf。在早期版本中,您可以如下模拟它。
Long version:
长版:
Here is the expected behavior for snprintf:
这是 snprintf 的预期行为:
int snprintf( char* buffer, std::size_t buf_size, const char* format, ... );
Writes at most
buf_size - 1characters to a buffer. The resulting character string will be terminated with a null character, unlessbuf_sizeis zero. Ifbuf_sizeis zero, nothing is written andbuffermay be a null pointer. The return value is the number of characters that would have been written assuming unlimitedbuf_size, not counting the terminating null character.
最多将
buf_size - 1字符写入缓冲区。结果字符串将以空字符终止,除非buf_size为零。如果buf_size为零,则不写入任何内容并且buffer可能是空指针。返回值是假设无限制写入的字符数buf_size,不计算终止空字符。
Releases prior to Visual Studio 2015 didn't have a conformant implementation. There are instead non-standard extensions such as _snprintf()(which doesn't write null-terminator on overflow) and _snprintf_s()(which can enforce null-termination, but returns -1 on overflow instead of the number of characters that would have been written).
Visual Studio 2015 之前的版本没有一致的实现。取而代之的是非标准扩展,例如_snprintf()(它不会在溢出时写入空终止符)和_snprintf_s()(它可以强制执行空终止,但在溢出时返回 -1 而不是本应写入的字符数)。
Suggested fallback for VS 2005 and up:
VS 2005 及更高版本的建议回退:
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf c99_snprintf
#define vsnprintf c99_vsnprintf
__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = c99_vsnprintf(outBuf, size, format, ap);
va_end(ap);
return count;
}
#endif
回答by kennytm
snprintfis not part of C89. It's standard only in C99. Microsoft has no plan supporting C99.
snprintf不是 C89 的一部分。它仅在 C99 中是标准配置。Microsoft没有支持 C99 的计划。
(But it's also standard in C++0x...!)
(但它也是 C++0x 中的标准...!)
See other answers below for a workaround.
有关解决方法,请参阅下面的其他答案。
回答by Stefan Steiger
If you don't need the return value, you could also just define snprintf as _snprintf_s
如果不需要返回值,也可以将 snprintf 定义为 _snprintf_s
#define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
回答by Il-Bhima
I believe the Windows equivalent is sprintf_s
我相信 Windows 等价物是 sprintf_s
回答by Marco Pracucci
Another safe replacement of snprintf()and vsnprintf()is provided by ffmpeg. You can checkout the source here(suggested).
ffmpeg 提供了snprintf()和 的另一个安全替代品vsnprintf()。您可以在此处查看源代码(建议)。
回答by andertavares
I tried @Valentin Milea's code but I've got access violation errors. The only thing that worked for me was Insane Coding's implementation: http://asprintf.insanecoding.org/
我尝试了@Valentin Milea 的代码,但我遇到了访问冲突错误。唯一对我有用的是疯狂编码的实现:http: //asprintf.insanecoding.org/
Specifically, I was working with VC++2008 legacy code. From Insane Coding's implementation (can be downloaded from the link above), I used three files: asprintf.c, asprintf.hand vasprintf-msvc.c. Other files were for other versions of MSVC.
具体来说,我正在使用 VC++2008 遗留代码。从 Insane Coding 的实现(可以从上面的链接下载),我使用了三个文件:asprintf.c,asprintf.h和vasprintf-msvc.c. 其他文件用于其他版本的 MSVC。
[EDIT] For completeness, their contents are as follows:
[编辑] 为完整起见,它们的内容如下:
asprintf.h:
asprintf.h:
#ifndef INSANE_ASPRINTF_H
#define INSANE_ASPRINTF_H
#ifndef __cplusplus
#include <stdarg.h>
#else
#include <cstdarg>
extern "C"
{
#endif
#define insane_free(ptr) { free(ptr); ptr = 0; }
int vasprintf(char **strp, const char *fmt, va_list ap);
int asprintf(char **strp, const char *fmt, ...);
#ifdef __cplusplus
}
#endif
#endif
asprintf.c:
asprintf.c:
#include "asprintf.h"
int asprintf(char **strp, const char *fmt, ...)
{
int r;
va_list ap;
va_start(ap, fmt);
r = vasprintf(strp, fmt, ap);
va_end(ap);
return(r);
}
vasprintf-msvc.c:
vasprintf-msvc.c:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "asprintf.h"
int vasprintf(char **strp, const char *fmt, va_list ap)
{
int r = -1, size = _vscprintf(fmt, ap);
if ((size >= 0) && (size < INT_MAX))
{
*strp = (char *)malloc(size+1); //+1 for null
if (*strp)
{
r = vsnprintf(*strp, size+1, fmt, ap); //+1 for null
if ((r < 0) || (r > size))
{
insane_free(*strp);
r = -1;
}
}
}
else { *strp = 0; }
return(r);
}
Usage (part of test.cprovided by Insane Coding):
用法(部分test.c由 Insane Coding 提供):
#include <stdio.h>
#include <stdlib.h>
#include "asprintf.h"
int main()
{
char *s;
if (asprintf(&s, "Hello, %d in hex padded to 8 digits is: %08x\n", 15, 15) != -1)
{
puts(s);
insane_free(s);
}
}

