简体   繁体   English

snprintf和Visual Studio 2010

[英]snprintf and Visual Studio 2010

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':找不到标识符)

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年?

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 - 1 characters to a buffer. 最多写入buf_size - 1字符到缓冲区。 The resulting character string will be terminated with a null character, unless buf_size is zero. 除非buf_size为零,否则生成的字符串将以空字符终止。 If buf_size is zero, nothing is written and buffer may be a null pointer. 如果buf_size为零, buf_size写入任何内容, buffer可能为空指针。 The return value is the number of characters that would have been written assuming unlimited buf_size , not counting the terminating null character. 返回值是假设无限制的buf_size而不是计算终止空字符而写入的字符数。

Releases prior to Visual Studio 2015 didn't have a conformant implementation. Visual Studio 2015之前的版本没有符合要求的实现。 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). 相反,非标准扩展(例如_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

snprintf is not part of C89. snprintf不是C89的一部分。 It's standard only in C99. 它仅在C99中是标准配置。 Microsoft has no plan supporting C99 . 微软没有支持C99的计划

(But it's also standard in C++0x...!) (但它也是C ++ 0x中的标准......)

See other answers below for a workaround. 请参阅下面的其他答案以获得解决方法。

如果您不需要返回值,也可以将snprintf定义为_snprintf_s

#define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)

我相信Windows的等价物是sprintf_s

Another safe replacement of snprintf() and vsnprintf() is provided by ffmpeg. ffmpeg提供了snprintf()vsnprintf()另一个安全替代品。 You can checkout the source here (suggested). 你可以在这里查看来源 (建议)。

I tried @Valentin Milea's code but I've got access violation errors. 我尝试了@Valentin Milea的代码,但我遇到了访问冲突错误。 The only thing that worked for me was Insane Coding's implementation: http://asprintf.insanecoding.org/ 对我来说唯一有用的是Insane Coding的实现: http//asprintf.insanecoding.org/

Specifically, I was working with VC++2008 legacy code. 具体来说,我正在使用VC ++ 2008遗留代码。 From Insane Coding's implementation (can be downloaded from the link above), I used three files: asprintf.c , asprintf.h and vasprintf-msvc.c . 从Insane Coding的实现(可以从上面的链接下载),我使用了三个文件: asprintf.casprintf.hvasprintf-msvc.c Other files were for other versions of MSVC. 其他文件适用于其他版本的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.c provided by Insane Coding): 用法(由Insane Coding提供的test.c一部分):

#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);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM