snprintf和Visual Studio 2010

And*_*rew 100 c visual-studio-2010

我很遗憾被迫使用VS 2010进行项目,并注意到以下代码仍然不使用非标准兼容编译器构建:

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    char buffer[512];

    snprintf(buffer, sizeof(buffer), "SomeString");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(编译错误:C3861:'snprintf':找不到标识符)

我记得这是VS 2005的情况,我很震惊地看到它还没有被修复.

有没有人知道微软是否有计划将他们的标准C库迁移到2010年?

Val*_*lea 85

简短的说明: Microsoft最终在Visual Studio 2015中实现了snprintf.在早期版本中,您可以按如下方式模拟它.


长版:

以下是snprintf的预期行为:

int snprintf( char* buffer, std::size_t buf_size, const char* format, ... );
Run Code Online (Sandbox Code Playgroud)

将大多数buf_size - 1字符写入缓冲区.除非buf_size为零,否则生成的字符串将以空字符终止 .如果buf_size为零,则不写入任何内容,并且 buffer可能是空指针.返回值是假设无限制写入的字符数buf_size,不包括终止空字符.

Visual Studio 2015之前的版本没有符合要求的实现.相反,非标准扩展(例如,_snprintf()在溢出时不写空终止符)和_snprintf_s()(它可以强制执行空终止,但在溢出时返回-1而不是已经写入的字符数).

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
Run Code Online (Sandbox Code Playgroud)

  • 截至2014年6月,即使使用Update 2,Visual Studio仍然没有"完整"的C99支持.[此博客](http://blogs.msdn.com/b/vcblog/archive/2013/07/19/ c99-library-support-in-visual-studio-2013.aspx)给出了MSVC 2013的C99支持简介.由于snprintf()系列函数现在是C++ 11标准的一部分,MSVC在C语言中落后于clang和gcc ++ 11实现! (2认同)
  • 使用VS2014,添加了带有snprintf和vsnprintf的C99标准.请参阅http://blogs.msdn.com/b/vcblog/archive/2014/06/18/crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1.aspx. (2认同)

ken*_*ytm 32

snprintf不属于C89.它仅在C99中是标准配置.微软没有支持C99的计划.

(但它也是C++ 0x中的标准......)

请参阅下面的其他答案以获得解决方法.

  • 只有你生活在1990年和1999年之间. (15认同)
  • @DeadMG - 错了.cl.exe支持/ Tc选项,它指示编译器将文件编译为C代码.此外,MSVC附带了一个标准C库的版本. (7认同)
  • -1,Microsoft的`_snprintf`是一个不安全的函数,其行为与`snprintf`不同(它不一定添加空终止符),因此这个答案中给出的建议具有误导性和危险性. (6认同)
  • 然而,这不是一个好的解决方法......因为snprintf和_snprintf行为存在差异.处理缓冲区空间不足时,_snprintf会延迟处理null终止符. (5认同)
  • @DeadMG - 然而,它确实支持C90标准以及C99的一些位,使其成为C编译器. (3认同)
  • 仅仅因为编译器在技术上可以编译C代码并不能使它成为一个真正的C编译器,因为它没有针对过去十年达到的标准进行更新. (2认同)
  • 这是评论,而不是答案.还有,死链接. (2认同)

Ste*_*ger 8

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

#define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)


Il-*_*ima 3

我相信 Windows 的等价物是sprintf_s

  • `sprintf_s` 的行为与 `snprintf` 不同。 (7认同)
  • @AndrewBainbridge——你截断了文档。完整的句子是“如果缓冲区对于正在打印的文本来说太小,则缓冲区将设置为空字符串并调用无效参数处理程序。” 无效参数句柄的默认行为是终止您的程序。如果您想使用 _s 系列进行截断,则需要使用 snprintf_s 和 _TRUNCATE 标志。是的,不幸的是 _s 函数没有提供方便的截断方法。另一方面, _s 函数确实使用模板魔法来推断缓冲区大小,这非常好。 (2认同)